forked from sailfishos/ofono
Compare commits
56 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 |
@@ -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,6 +125,9 @@ 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 \
|
||||||
@@ -616,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
|
||||||
@@ -651,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) \
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ struct ril_data_priv {
|
|||||||
struct ril_data_request *req_queue;
|
struct ril_data_request *req_queue;
|
||||||
struct ril_data_request *pending_req;
|
struct ril_data_request *pending_req;
|
||||||
|
|
||||||
|
enum ril_data_allow_data_opt allow_data;
|
||||||
char *log_prefix;
|
char *log_prefix;
|
||||||
guint query_id;
|
guint query_id;
|
||||||
gulong io_event_id;
|
gulong io_event_id;
|
||||||
@@ -158,6 +159,7 @@ struct ril_data_request_setup {
|
|||||||
char *password;
|
char *password;
|
||||||
enum ofono_gprs_proto proto;
|
enum ofono_gprs_proto proto;
|
||||||
enum ofono_gprs_auth_method auth_method;
|
enum ofono_gprs_auth_method auth_method;
|
||||||
|
int retry_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_data_request_deact {
|
struct ril_data_request_deact {
|
||||||
@@ -686,8 +688,6 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
|||||||
struct ril_data_call_list *list = NULL;
|
struct ril_data_call_list *list = NULL;
|
||||||
struct ril_data_call *call = NULL;
|
struct ril_data_call *call = NULL;
|
||||||
|
|
||||||
ril_data_request_completed(req);
|
|
||||||
|
|
||||||
if (ril_status == RIL_E_SUCCESS) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
list = ril_data_call_list_parse(data, len);
|
list = ril_data_call_list_parse(data, len);
|
||||||
}
|
}
|
||||||
@@ -701,6 +701,22 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (call && call->status == PDP_FAIL_ERROR_UNSPECIFIED &&
|
||||||
|
!setup->retry_count) {
|
||||||
|
/*
|
||||||
|
* Retry silently according to comment in ril.h
|
||||||
|
* (no more than once though)
|
||||||
|
*/
|
||||||
|
DBG("retrying silently");
|
||||||
|
setup->retry_count++;
|
||||||
|
req->pending_id = 0;
|
||||||
|
req->submit(req);
|
||||||
|
ril_data_call_list_free(list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ril_data_request_completed(req);
|
||||||
|
|
||||||
if (call && call->status == PDP_FAIL_NONE) {
|
if (call && call->status == PDP_FAIL_NONE) {
|
||||||
if (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
|
if (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
|
||||||
DBG("data call(s) added");
|
DBG("data call(s) added");
|
||||||
@@ -1004,7 +1020,7 @@ static void ril_data_settings_changed(struct ril_sim_settings *settings,
|
|||||||
|
|
||||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
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)
|
||||||
{
|
{
|
||||||
GASSERT(dm);
|
GASSERT(dm);
|
||||||
if (G_LIKELY(dm)) {
|
if (G_LIKELY(dm)) {
|
||||||
@@ -1013,6 +1029,21 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
|||||||
struct ril_sim_settings *settings = network->settings;
|
struct ril_sim_settings *settings = network->settings;
|
||||||
GRilIoRequest *req = grilio_request_new();
|
GRilIoRequest *req = grilio_request_new();
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case RIL_ALLOW_DATA_ON:
|
||||||
|
case RIL_ALLOW_DATA_OFF:
|
||||||
|
priv->allow_data = opt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* When RIL_REQUEST_ALLOW_DATA first appeared in ril.h
|
||||||
|
* RIL_VERSION was 10
|
||||||
|
*/
|
||||||
|
priv->allow_data = (io->ril_version > 10) ?
|
||||||
|
RIL_ALLOW_DATA_ON : RIL_ALLOW_DATA_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
priv->log_prefix = (name && name[0]) ?
|
priv->log_prefix = (name && name[0]) ?
|
||||||
g_strconcat(name, " ", NULL) : g_strdup("");
|
g_strconcat(name, " ", NULL) : g_strdup("");
|
||||||
|
|
||||||
@@ -1449,11 +1480,8 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
|||||||
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
|
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* RIL_VERSION in ril.h was 10 when RIL_REQUEST_ALLOW_DATA first
|
if (priv->allow_data == RIL_ALLOW_DATA_ON) {
|
||||||
* appeared there.
|
|
||||||
*/
|
|
||||||
if (priv->io->ril_version >= 10) {
|
|
||||||
ril_data_request_queue(ril_data_allow_new(data));
|
ril_data_request_queue(ril_data_allow_new(data));
|
||||||
} else {
|
} else {
|
||||||
priv->flags |= RIL_DATA_FLAG_ON;
|
priv->flags |= RIL_DATA_FLAG_ON;
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ enum ril_data_manager_flags {
|
|||||||
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
|
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 {
|
enum ril_data_role {
|
||||||
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
||||||
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
||||||
@@ -74,7 +80,7 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
|||||||
|
|
||||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
struct ril_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);
|
||||||
gboolean ril_data_allowed(struct ril_data *data);
|
gboolean ril_data_allowed(struct ril_data *data);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ enum ril_ecclist_signal {
|
|||||||
SIGNAL_COUNT
|
SIGNAL_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIGNAL_LIST_CHANGED_NAME "ril-sim-settings-imsi-changed"
|
#define SIGNAL_LIST_CHANGED_NAME "ril-ecclist-changed"
|
||||||
|
|
||||||
static guint ril_ecclist_signals[SIGNAL_COUNT] = { 0 };
|
static guint ril_ecclist_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
|||||||
@@ -141,16 +141,28 @@ 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) {
|
||||||
/* Complete the deactivate request */
|
struct ril_gprs_context_call deact = gcd->deactivate;
|
||||||
ofono_gprs_context_cb_t cb = gcd->deactivate.cb;
|
|
||||||
gpointer data = gcd->deactivate.data;
|
|
||||||
|
|
||||||
ril_data_request_cancel(gcd->deactivate.req);
|
/*
|
||||||
|
* 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));
|
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
||||||
if (cb) {
|
ril_data_request_cancel(deact.req);
|
||||||
|
if (deact.cb) {
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
ofono_info("Deactivated data call");
|
ofono_info("Deactivated data call");
|
||||||
cb(ril_error_ok(&error), data);
|
deact.cb(ril_error_ok(&error), deact.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,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",
|
||||||
@@ -444,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);
|
||||||
@@ -624,7 +636,15 @@ 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);
|
||||||
|
|
||||||
|
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);
|
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. */
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (mce->daemon_watch) {
|
|
||||||
g_dbus_remove_watch(mce->conn, mce->daemon_watch);
|
|
||||||
}
|
}
|
||||||
dbus_connection_unref(mce->conn);
|
|
||||||
grilio_channel_unref(mce->io);
|
void ril_mce_unref(struct ril_mce *self)
|
||||||
g_free(mce);
|
{
|
||||||
|
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 */
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ struct ril_modem_data {
|
|||||||
char *imei;
|
char *imei;
|
||||||
char *ecclist_file;
|
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;
|
||||||
@@ -140,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) {
|
||||||
@@ -273,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);
|
||||||
@@ -322,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,
|
||||||
@@ -443,6 +420,12 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
|||||||
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);
|
||||||
@@ -473,6 +456,15 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
|||||||
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",
|
||||||
|
|||||||
@@ -403,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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_oem_raw_request(struct ofono_oem_raw *raw,
|
__ofono_dbus_pending_reply(&msg, reply);
|
||||||
const struct ofono_oem_raw_request *request,
|
}
|
||||||
ofono_oem_raw_query_cb_t cb, void *data)
|
|
||||||
|
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
DBusMessageIter it;
|
||||||
GRilIoRequest *req = grilio_request_sized_new(request->length);
|
struct ril_oem_raw *oem = user_data;
|
||||||
|
|
||||||
grilio_request_append_bytes(req, request->data, request->length);
|
dbus_message_iter_init(msg, &it);
|
||||||
grilio_queue_send_request_full(od->q, req, RIL_REQUEST_OEM_HOOK_RAW,
|
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
|
||||||
ril_oem_raw_request_cb, ril_oem_raw_cbd_free,
|
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
|
||||||
ril_oem_raw_cbd_new(cb, data));
|
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);
|
grilio_request_unref(req);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
DBG_(oem, "Unexpected signature");
|
||||||
|
return __ofono_error_invalid_args(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_oem_raw_register(gpointer user_data)
|
static const GDBusMethodTable ril_oem_raw_methods[] = {
|
||||||
{
|
{ GDBUS_ASYNC_METHOD("Send",
|
||||||
struct ofono_oem_raw *raw = user_data;
|
GDBUS_ARGS({ "request", "ay" }),
|
||||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
GDBUS_ARGS({ "response", "ay" }),
|
||||||
|
ril_oem_raw_send) },
|
||||||
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,9 +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_info.h"
|
||||||
#include "ril_sim_settings.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"
|
||||||
@@ -48,10 +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 RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
|
||||||
|
|
||||||
#define RILMODEM_CONF_GROUP "Settings"
|
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
|
||||||
#define RILMODEM_CONF_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
|
||||||
@@ -63,6 +65,7 @@
|
|||||||
#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_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"
|
||||||
@@ -83,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;
|
||||||
@@ -102,9 +108,10 @@ struct ril_slot {
|
|||||||
char *sockpath;
|
char *sockpath;
|
||||||
char *sub;
|
char *sub;
|
||||||
char *ecclist_file;
|
char *ecclist_file;
|
||||||
gint timeout; /* RIL timeout, in milliseconds */
|
int timeout; /* RIL timeout, in milliseconds */
|
||||||
int index;
|
int index;
|
||||||
int sim_flags;
|
int sim_flags;
|
||||||
|
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_modem *modem;
|
struct ril_modem *modem;
|
||||||
@@ -116,6 +123,9 @@ struct ril_slot {
|
|||||||
struct ril_sim_info *sim_info;
|
struct ril_sim_info *sim_info;
|
||||||
struct ril_sim_info_dbus *sim_info_dbus;
|
struct ril_sim_info_dbus *sim_info_dbus;
|
||||||
struct ril_sim_settings *sim_settings;
|
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];
|
||||||
@@ -141,15 +151,24 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,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);
|
||||||
@@ -233,16 +275,16 @@ 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, RIL_DATA_ROLE_NONE);
|
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
||||||
ril_data_unref(slot->data);
|
ril_data_unref(slot->data);
|
||||||
@@ -255,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;
|
||||||
}
|
}
|
||||||
@@ -488,8 +531,9 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (plugin->pub.ready != ready) {
|
if (plugin->pub.ready != ready) {
|
||||||
DBG("%sready", ready ? "" : "not ");
|
|
||||||
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);
|
ril_plugin_dbus_signal(plugin->dbus, RIL_PLUGIN_SIGNAL_READY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,11 +687,21 @@ 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->oem_raw) {
|
||||||
|
ril_oem_raw_free(slot->oem_raw);
|
||||||
|
slot->oem_raw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (slot->sim_info_dbus) {
|
if (slot->sim_info_dbus) {
|
||||||
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
||||||
slot->sim_info_dbus = NULL;
|
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;
|
||||||
ril_radio_set_online(slot->radio, FALSE);
|
ril_radio_set_online(slot->radio, FALSE);
|
||||||
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
||||||
@@ -657,12 +711,7 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
/* Turn prefix off */
|
static const GLogModule* log_module = &ril_debug_trace_module;
|
||||||
static GLogModule log_module = {
|
|
||||||
.max_level = GLOG_LEVEL_VERBOSE,
|
|
||||||
.level = GLOG_LEVEL_VERBOSE
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -675,21 +724,21 @@ 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_VERBOSE, "%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_VERBOSE, "%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_VERBOSE, "%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) {
|
||||||
@@ -705,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) {
|
||||||
@@ -723,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);
|
||||||
@@ -737,11 +786,6 @@ static const char *ril_plugin_log_prefix(struct ril_slot *slot)
|
|||||||
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : "";
|
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_plugin_can_create_modem(struct ril_slot *slot)
|
|
||||||
{
|
|
||||||
return slot->pub.enabled && slot->io && slot->io->connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_plugin_create_modem(struct ril_slot *slot)
|
static void ril_plugin_create_modem(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
@@ -768,6 +812,14 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
|
|||||||
|
|
||||||
slot->sim_info_dbus = ril_sim_info_dbus_new(slot->modem,
|
slot->sim_info_dbus = ril_sim_info_dbus_new(slot->modem,
|
||||||
slot->sim_info);
|
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);
|
||||||
@@ -778,42 +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);
|
|
||||||
}
|
/*
|
||||||
ril_plugin_update_ready(plugin);
|
* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -842,6 +901,7 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
|||||||
{
|
{
|
||||||
struct ril_plugin_priv *plugin = slot->plugin;
|
struct ril_plugin_priv *plugin = slot->plugin;
|
||||||
const char *log_prefix = ril_plugin_log_prefix(slot);
|
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);
|
||||||
@@ -849,12 +909,19 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
|||||||
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);
|
||||||
@@ -874,15 +941,20 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
|||||||
GASSERT(!slot->network);
|
GASSERT(!slot->network);
|
||||||
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
|
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
|
||||||
slot->sim_card, slot->sim_settings);
|
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, log_prefix,
|
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
|
||||||
slot->radio, slot->network, slot->io);
|
slot->radio, slot->network, slot->io, slot->allow_data_opt);
|
||||||
|
|
||||||
if (ril_plugin_can_create_modem(slot) && !slot->modem) {
|
GASSERT(!slot->cell_info);
|
||||||
ril_plugin_create_modem(slot);
|
if (slot->io->ril_version > 8) {
|
||||||
|
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
|
||||||
|
plugin->mce, slot->radio, slot->sim_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ril_plugin_send_screen_state(slot);
|
||||||
|
ril_plugin_check_modem(slot);
|
||||||
ril_plugin_update_ready(plugin);
|
ril_plugin_update_ready(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,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);
|
||||||
@@ -971,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);
|
||||||
@@ -980,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 {
|
||||||
@@ -993,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 {
|
||||||
@@ -1002,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)
|
||||||
{
|
{
|
||||||
@@ -1023,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);
|
||||||
@@ -1042,42 +1102,28 @@ 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);
|
||||||
@@ -1085,8 +1131,22 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND) ?
|
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND) ?
|
||||||
"on" : "off");
|
"on" : "off");
|
||||||
|
|
||||||
slot->ecclist_file = g_key_file_get_string(file, group,
|
strval = ril_config_get_string(file, group,
|
||||||
RILCONF_ECCLIST_FILE, NULL);
|
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]) {
|
if (slot->ecclist_file && slot->ecclist_file[0]) {
|
||||||
DBG("%s: ecclist file %s", group, slot->ecclist_file);
|
DBG("%s: ecclist file %s", group, slot->ecclist_file);
|
||||||
slot->pub.ecclist_file = slot->ecclist_file;
|
slot->pub.ecclist_file = slot->ecclist_file;
|
||||||
@@ -1171,10 +1231,10 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
|
|||||||
if (slot) {
|
if (slot) {
|
||||||
list = ril_plugin_add_slot(list, slot);
|
list = ril_plugin_add_slot(list, slot);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(group, RILMODEM_CONF_GROUP)) {
|
} else if (!strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||||
/* Plugin configuration */
|
/* Plugin configuration */
|
||||||
ril_plugin_read_config_flag(file, group,
|
ril_config_get_flag(file, group,
|
||||||
RILMODEM_CONF_3GHANDOVER,
|
RILCONF_SETTINGS_3GHANDOVER,
|
||||||
RIL_DATA_MANAGER_3GLTE_HANDOVER,
|
RIL_DATA_MANAGER_3GLTE_HANDOVER,
|
||||||
&ps->dm_flags);
|
&ps->dm_flags);
|
||||||
}
|
}
|
||||||
@@ -1256,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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1441,7 +1499,7 @@ 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(NULL);
|
slot->sim_info = ril_sim_info_new(ril_plugin_log_prefix(slot));
|
||||||
slot->sim_settings = ril_sim_settings_new(&slot->config);
|
slot->sim_settings = ril_sim_settings_new(&slot->config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1459,19 +1517,19 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1498,7 +1556,22 @@ static int ril_plugin_init(void)
|
|||||||
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();
|
||||||
@@ -1508,6 +1581,9 @@ static int ril_plugin_init(void)
|
|||||||
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(ps.dm_flags);
|
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) {
|
||||||
/*
|
/*
|
||||||
@@ -1564,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) */
|
||||||
@@ -1576,6 +1651,12 @@ static int ril_plugin_init(void)
|
|||||||
*/
|
*/
|
||||||
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 */
|
/* This will set 'ready' flag if we have no modems at all */
|
||||||
ril_plugin_update_ready(ril_plugin);
|
ril_plugin_update_ready(ril_plugin);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1602,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>
|
||||||
@@ -99,11 +98,21 @@ 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_oem_raw;
|
||||||
|
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *md,
|
||||||
|
const char *log_prefix);
|
||||||
|
void ril_oem_raw_free(struct ril_oem_raw *raw);
|
||||||
|
|
||||||
struct ril_sim_info_dbus;
|
struct ril_sim_info_dbus;
|
||||||
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||||
struct ril_sim_info *info);
|
struct ril_sim_info *info);
|
||||||
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus);
|
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;
|
||||||
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);
|
||||||
@@ -118,7 +127,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
|||||||
struct ril_network *network, struct ril_sim_card *card,
|
struct ril_network *network, struct ril_sim_card *card,
|
||||||
struct ril_data *data, struct ril_sim_settings *settings);
|
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);
|
||||||
@@ -132,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);
|
||||||
|
|
||||||
@@ -158,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;
|
||||||
|
|||||||
@@ -67,7 +67,6 @@
|
|||||||
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;
|
||||||
@@ -386,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))) {
|
||||||
|
struct ofono_error error;
|
||||||
|
cb(ril_error_failure(&error), -1, -1, -1, NULL,
|
||||||
|
EF_STATUS_INVALIDATED, 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)
|
|
||||||
{
|
|
||||||
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,
|
||||||
@@ -458,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,
|
||||||
@@ -502,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)
|
||||||
@@ -570,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));
|
||||||
@@ -1045,18 +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);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
@@ -1077,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) {
|
||||||
@@ -1093,7 +1023,6 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_sim_info.h"
|
#include "ril_sim_info.h"
|
||||||
|
#include "ril_network.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
#include <ofono/sim.h>
|
#include <ofono/sim.h>
|
||||||
@@ -29,10 +30,15 @@
|
|||||||
#define RIL_SIM_ICCID_MAP "iccidmap"
|
#define RIL_SIM_ICCID_MAP "iccidmap"
|
||||||
#define RIL_SIM_ICCID_MAP_IMSI "imsi"
|
#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 GObjectClass RilSimInfoClass;
|
||||||
typedef struct ril_sim_info RilSimInfo;
|
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_remove_cb_t)(struct ofono_sim *sim,
|
||||||
|
unsigned int id);
|
||||||
typedef void (*ril_sim_info_set_value_cb_t)(struct ril_sim_info *info,
|
typedef void (*ril_sim_info_set_value_cb_t)(struct ril_sim_info *info,
|
||||||
const char *value);
|
const char *value);
|
||||||
|
|
||||||
@@ -44,14 +50,20 @@ struct ril_sim_info_watch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ril_sim_info_priv {
|
struct ril_sim_info_priv {
|
||||||
|
char *log_prefix;
|
||||||
char *iccid;
|
char *iccid;
|
||||||
char *imsi;
|
char *imsi;
|
||||||
char *spn;
|
char *cached_spn;
|
||||||
|
char *sim_spn;
|
||||||
|
char *public_spn;
|
||||||
|
char default_spn[RIL_SIM_DEFAULT_SPN_BUFSIZE];
|
||||||
struct ofono_sim *sim;
|
struct ofono_sim *sim;
|
||||||
struct ril_sim_info_watch state_watch;
|
struct ril_sim_info_watch state_watch;
|
||||||
struct ril_sim_info_watch iccid_watch;
|
struct ril_sim_info_watch iccid_watch;
|
||||||
struct ril_sim_info_watch imsi_watch;
|
struct ril_sim_info_watch imsi_watch;
|
||||||
struct ril_sim_info_watch spn_watch;
|
struct ril_sim_info_watch spn_watch;
|
||||||
|
struct ril_network *network;
|
||||||
|
gulong network_operator_changed_id;
|
||||||
gboolean update_imsi_cache;
|
gboolean update_imsi_cache;
|
||||||
gboolean update_iccid_map;
|
gboolean update_iccid_map;
|
||||||
};
|
};
|
||||||
@@ -80,6 +92,8 @@ G_DEFINE_TYPE(RilSimInfo, ril_sim_info, G_TYPE_OBJECT)
|
|||||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
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,
|
static void ril_sim_info_signal_emit(struct ril_sim_info *self,
|
||||||
enum ril_sim_info_signal id)
|
enum ril_sim_info_signal id)
|
||||||
{
|
{
|
||||||
@@ -105,7 +119,8 @@ static void ril_sim_info_watch_remove(struct ril_sim_info_watch *watch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_info_remove_spn_watch(struct ofono_sim *sim, unsigned int id)
|
static void ril_sim_info_remove_spn_watch(struct ofono_sim *sim,
|
||||||
|
unsigned int id)
|
||||||
{
|
{
|
||||||
ofono_sim_remove_spn_watch(sim, &id);
|
ofono_sim_remove_spn_watch(sim, &id);
|
||||||
}
|
}
|
||||||
@@ -115,14 +130,34 @@ static void ril_sim_info_update_imsi_cache(struct ril_sim_info *self)
|
|||||||
struct ril_sim_info_priv *priv = self->priv;
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
if (priv->update_imsi_cache && priv->imsi && priv->imsi[0] &&
|
if (priv->update_imsi_cache && priv->imsi && priv->imsi[0] &&
|
||||||
priv->spn && priv->spn[0]) {
|
priv->cached_spn && priv->cached_spn[0]) {
|
||||||
|
gboolean save = FALSE;
|
||||||
const char *store = RIL_SIM_INFO_STORE;
|
const char *store = RIL_SIM_INFO_STORE;
|
||||||
GKeyFile *cache = storage_open(priv->imsi, 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);
|
||||||
|
|
||||||
DBG("Updating " STORAGEDIR "/%s/%s", priv->imsi, store);
|
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||||
|
save = TRUE;
|
||||||
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
||||||
RIL_SIM_INFO_STORE_SPN, priv->spn);
|
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);
|
storage_close(priv->imsi, store, cache, TRUE);
|
||||||
|
} else {
|
||||||
|
g_key_file_free(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(spn);
|
||||||
priv->update_imsi_cache = FALSE;
|
priv->update_imsi_cache = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,11 +170,24 @@ static void ril_sim_info_update_iccid_map(struct ril_sim_info *self)
|
|||||||
priv->imsi && priv->imsi[0]) {
|
priv->imsi && priv->imsi[0]) {
|
||||||
const char *store = RIL_SIM_ICCID_MAP;
|
const char *store = RIL_SIM_ICCID_MAP;
|
||||||
GKeyFile *map = storage_open(NULL, store);
|
GKeyFile *map = storage_open(NULL, store);
|
||||||
|
char *imsi = g_key_file_get_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||||
|
priv->iccid, NULL);
|
||||||
|
|
||||||
DBG("Updating " STORAGEDIR "/%s", store);
|
/*
|
||||||
|
* 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,
|
g_key_file_set_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||||
priv->iccid, priv->imsi);
|
priv->iccid, priv->imsi);
|
||||||
storage_close(NULL, store, map, TRUE);
|
storage_close(NULL, store, map, TRUE);
|
||||||
|
} else {
|
||||||
|
g_key_file_free(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(imsi);
|
||||||
priv->update_iccid_map = FALSE;
|
priv->update_iccid_map = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,19 +206,112 @@ static void ril_sim_info_set_imsi(struct ril_sim_info *self, const char *imsi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_info_set_spn(struct ril_sim_info *self, const char *spn)
|
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;
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
if (g_strcmp0(priv->spn, spn)) {
|
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||||
g_free(priv->spn);
|
DBG_(self, "cached spn \"%s\"", spn);
|
||||||
self->spn = priv->spn = g_strdup(spn);
|
g_free(priv->cached_spn);
|
||||||
|
priv->cached_spn = g_strdup(spn);
|
||||||
priv->update_imsi_cache = TRUE;
|
priv->update_imsi_cache = TRUE;
|
||||||
ril_sim_info_update_imsi_cache(self);
|
ril_sim_info_update_imsi_cache(self);
|
||||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
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)
|
static void ril_sim_info_load_cache(struct ril_sim_info *self)
|
||||||
{
|
{
|
||||||
struct ril_sim_info_priv *priv = self->priv;
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
@@ -184,18 +325,19 @@ static void ril_sim_info_load_cache(struct ril_sim_info *self)
|
|||||||
if (imsi && imsi[0] && g_strcmp0(priv->imsi, imsi)) {
|
if (imsi && imsi[0] && g_strcmp0(priv->imsi, imsi)) {
|
||||||
if (priv->imsi && priv->imsi[0]) {
|
if (priv->imsi && priv->imsi[0]) {
|
||||||
/* Need to update ICCID -> IMSI map */
|
/* Need to update ICCID -> IMSI map */
|
||||||
DBG("IMSI changed %s -> %s", priv->imsi, imsi);
|
DBG_(self, "IMSI changed %s -> %s",
|
||||||
|
priv->imsi, imsi);
|
||||||
priv->update_imsi_cache = TRUE;
|
priv->update_imsi_cache = TRUE;
|
||||||
}
|
}
|
||||||
g_free(priv->imsi);
|
g_free(priv->imsi);
|
||||||
self->imsi = priv->imsi = imsi;
|
self->imsi = priv->imsi = imsi;
|
||||||
DBG("imsi[%s] = %s", priv->iccid, imsi);
|
DBG_(self, "imsi[%s] = %s", priv->iccid, imsi);
|
||||||
ril_sim_info_update_iccid_map(self);
|
ril_sim_info_update_iccid_map(self);
|
||||||
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||||
} else if (imsi) {
|
} else if (imsi) {
|
||||||
g_free(imsi);
|
g_free(imsi);
|
||||||
} else {
|
} else {
|
||||||
DBG("No imsi for iccid %s", priv->iccid);
|
DBG_(self, "no imsi for iccid %s", priv->iccid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,21 +348,22 @@ static void ril_sim_info_load_cache(struct ril_sim_info *self)
|
|||||||
RIL_SIM_INFO_STORE_SPN, NULL);
|
RIL_SIM_INFO_STORE_SPN, NULL);
|
||||||
g_key_file_free(cache);
|
g_key_file_free(cache);
|
||||||
|
|
||||||
if (spn && spn[0] && g_strcmp0(priv->spn, spn)) {
|
if (spn && spn[0] && g_strcmp0(priv->cached_spn, spn)) {
|
||||||
if (priv->spn && priv->spn[0]) {
|
if (priv->cached_spn && priv->cached_spn[0]) {
|
||||||
/* Need to update the cache file */
|
/* Need to update the cache file */
|
||||||
DBG("spn changing %s -> %s", priv->spn, spn);
|
DBG_(self, "spn changing %s -> %s",
|
||||||
|
priv->cached_spn, spn);
|
||||||
priv->update_imsi_cache = TRUE;
|
priv->update_imsi_cache = TRUE;
|
||||||
}
|
}
|
||||||
g_free(priv->spn);
|
g_free(priv->cached_spn);
|
||||||
self->spn = priv->spn = spn;
|
priv->cached_spn = spn;
|
||||||
DBG("spn[%s] = \"%s\"", priv->imsi, spn);
|
DBG_(self, "spn[%s] = \"%s\"", priv->imsi, spn);
|
||||||
ril_sim_info_update_imsi_cache(self);
|
ril_sim_info_update_imsi_cache(self);
|
||||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
ril_sim_info_update_public_spn(self);
|
||||||
} else if (spn) {
|
} else if (spn) {
|
||||||
g_free(spn);
|
g_free(spn);
|
||||||
} else {
|
} else {
|
||||||
DBG("No spn for imsi %s", priv->imsi);
|
DBG_(self, "no spn for imsi %s", priv->imsi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +385,8 @@ static void ril_sim_info_set_iccid(struct ril_sim_info *self, const char *iccid)
|
|||||||
static void ril_sim_info_imsi_watch_cb(const char *imsi, void *data)
|
static void ril_sim_info_imsi_watch_cb(const char *imsi, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim_info_watch *watch = data;
|
struct ril_sim_info_watch *watch = data;
|
||||||
DBG("%s", imsi);
|
|
||||||
|
DBG_(watch->info, "%s", imsi);
|
||||||
ril_sim_info_set_imsi(watch->info, imsi);
|
ril_sim_info_set_imsi(watch->info, imsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,14 +394,16 @@ static void ril_sim_info_spn_watch_cb(const char *spn, const char *dc,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim_info_watch *watch = data;
|
struct ril_sim_info_watch *watch = data;
|
||||||
DBG("%s", spn);
|
|
||||||
ril_sim_info_set_spn(watch->info, spn);
|
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)
|
static void ril_sim_info_iccid_watch_cb(const char *iccid, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim_info_watch *watch = data;
|
struct ril_sim_info_watch *watch = data;
|
||||||
DBG("%s", iccid);
|
|
||||||
|
DBG_(watch->info, "%s", iccid);
|
||||||
ril_sim_info_set_iccid(watch->info, iccid);
|
ril_sim_info_set_iccid(watch->info, iccid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +421,7 @@ static void ril_sim_info_handle_sim_state(struct ril_sim_info *self,
|
|||||||
struct ril_sim_info_priv *priv = self->priv;
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
struct ril_sim_info_watch *watch;
|
struct ril_sim_info_watch *watch;
|
||||||
|
|
||||||
DBG("%d", state);
|
DBG_(self, "%d", state);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case OFONO_SIM_STATE_READY:
|
case OFONO_SIM_STATE_READY:
|
||||||
@@ -314,6 +460,9 @@ static void ril_sim_info_handle_sim_state(struct ril_sim_info *self,
|
|||||||
ril_sim_info_watch_remove(&priv->iccid_watch);
|
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||||
break;
|
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,
|
static void ril_sim_info_state_watch_cb(enum ofono_sim_state new_state,
|
||||||
@@ -323,11 +472,12 @@ static void ril_sim_info_state_watch_cb(enum ofono_sim_state new_state,
|
|||||||
ril_sim_info_handle_sim_state(watch->info, new_state);
|
ril_sim_info_handle_sim_state(watch->info, new_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_sim_info *ril_sim_info_new(struct ofono_sim *sim)
|
struct ril_sim_info *ril_sim_info_new(const char *log_prefix)
|
||||||
{
|
{
|
||||||
struct ril_sim_info *self = g_object_new(RIL_SIMINFO_TYPE, NULL);
|
struct ril_sim_info *self = g_object_new(RIL_SIMINFO_TYPE, NULL);
|
||||||
|
|
||||||
ril_sim_info_set_ofono_sim(self, sim);
|
self->priv->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||||
|
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +498,8 @@ void ril_sim_info_unref(struct ril_sim_info *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ril_sim_info_set_ofono_sim(struct ril_sim_info *self, struct ofono_sim *sim)
|
void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
|
||||||
|
struct ofono_sim *sim)
|
||||||
{
|
{
|
||||||
if (G_LIKELY(self)) {
|
if (G_LIKELY(self)) {
|
||||||
struct ril_sim_info_priv *priv = self->priv;
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
@@ -370,10 +521,36 @@ void ril_sim_info_set_ofono_sim(struct ril_sim_info *self, struct ofono_sim *sim
|
|||||||
&priv->state_watch,
|
&priv->state_watch,
|
||||||
ril_sim_info_watch_done);
|
ril_sim_info_watch_done);
|
||||||
GASSERT(priv->state_watch.id);
|
GASSERT(priv->state_watch.id);
|
||||||
DBG("Attached to sim");
|
DBG_(self, "attached to sim");
|
||||||
ril_sim_info_handle_sim_state(self,
|
ril_sim_info_handle_sim_state(self,
|
||||||
ofono_sim_get_state(sim));
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,14 +599,14 @@ static void ril_sim_info_init(struct ril_sim_info *self)
|
|||||||
RIL_SIMINFO_TYPE, struct ril_sim_info_priv);
|
RIL_SIMINFO_TYPE, struct ril_sim_info_priv);
|
||||||
|
|
||||||
self->priv = priv;
|
self->priv = priv;
|
||||||
ril_sim_info_watch_init(self, &priv->state_watch, NULL,
|
ril_sim_info_watch_init(self, &priv->state_watch,
|
||||||
ofono_sim_remove_state_watch);
|
NULL, ofono_sim_remove_state_watch);
|
||||||
ril_sim_info_watch_init(self, &priv->iccid_watch, ril_sim_info_set_iccid,
|
ril_sim_info_watch_init(self, &priv->iccid_watch,
|
||||||
ofono_sim_remove_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,
|
ril_sim_info_watch_init(self, &priv->imsi_watch,
|
||||||
ofono_sim_remove_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_spn,
|
ril_sim_info_watch_init(self, &priv->spn_watch,
|
||||||
ril_sim_info_remove_spn_watch);
|
ril_sim_info_set_sim_spn, ril_sim_info_remove_spn_watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_info_dispose(GObject *object)
|
static void ril_sim_info_dispose(GObject *object)
|
||||||
@@ -437,14 +614,30 @@ static void ril_sim_info_dispose(GObject *object)
|
|||||||
struct ril_sim_info *self = RIL_SIMINFO(object);
|
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||||
|
|
||||||
ril_sim_info_set_ofono_sim(self, NULL);
|
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);
|
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)
|
static void ril_sim_info_class_init(RilSimInfoClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
object_class->dispose = ril_sim_info_dispose;
|
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));
|
g_type_class_add_private(klass, sizeof(struct ril_sim_info_priv));
|
||||||
NEW_SIGNAL(klass, ICCID);
|
NEW_SIGNAL(klass, ICCID);
|
||||||
NEW_SIGNAL(klass, IMSI);
|
NEW_SIGNAL(klass, IMSI);
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ struct ril_sim_info {
|
|||||||
struct ofono_sim;
|
struct ofono_sim;
|
||||||
typedef void (*ril_sim_info_cb_t)(struct ril_sim_info *info, void *arg);
|
typedef void (*ril_sim_info_cb_t)(struct ril_sim_info *info, void *arg);
|
||||||
|
|
||||||
struct ril_sim_info *ril_sim_info_new(struct ofono_sim *sim);
|
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);
|
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_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_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,
|
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *si,
|
||||||
ril_sim_info_cb_t cb, void *arg);
|
ril_sim_info_cb_t cb, void *arg);
|
||||||
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *si,
|
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *si,
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
|||||||
|
|
||||||
return dbus;
|
return dbus;
|
||||||
} else {
|
} else {
|
||||||
ofono_error("RIL D-Bus register failed");
|
ofono_error("CellInfo D-Bus register failed");
|
||||||
ril_sim_info_dbus_free(dbus);
|
ril_sim_info_dbus_free(dbus);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,12 +414,17 @@ 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,
|
||||||
|
SIM_EFSMS_FILEID,
|
||||||
|
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||||
|
rec, EFSMS_LENGTH,
|
||||||
|
sim_path, sizeof(sim_path),
|
||||||
ril_sms_on_sim_cb,
|
ril_sms_on_sim_cb,
|
||||||
ril_sms_on_sim_req_new(sd,rec));
|
ril_sms_on_sim_req_new(sd,rec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean ril_sms_register(gpointer user_data)
|
static gboolean ril_sms_register(gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -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,4 +1,4 @@
|
|||||||
# 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
|
||||||
#
|
#
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
# common settings are in the [Settings] section, all other sections
|
# common settings are in the [Settings] section, all other sections
|
||||||
# are 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]
|
[Settings]
|
||||||
|
|
||||||
@@ -83,3 +87,11 @@ socket=/dev/socket/rild
|
|||||||
# chmod 0644 /var/lib/ofono/ril.ecclist
|
# chmod 0644 /var/lib/ofono/ril.ecclist
|
||||||
#
|
#
|
||||||
#ecclistFile=/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
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct ofono_sim;
|
|||||||
#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;
|
||||||
@@ -46,6 +47,7 @@ struct ril_network;
|
|||||||
struct ril_sim_card;
|
struct ril_sim_card;
|
||||||
struct ril_sim_info;
|
struct ril_sim_info;
|
||||||
struct ril_sim_settings;
|
struct ril_sim_settings;
|
||||||
|
struct ril_cell_info;
|
||||||
|
|
||||||
struct ril_slot_config {
|
struct ril_slot_config {
|
||||||
guint slot;
|
guint slot;
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
#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,
|
||||||
@@ -43,7 +43,7 @@ struct ril_voicecall {
|
|||||||
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];
|
||||||
@@ -52,13 +52,6 @@ struct ril_voicecall {
|
|||||||
gulong ecclist_change_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 {
|
||||||
struct ofono_voicecall *vc;
|
struct ofono_voicecall *vc;
|
||||||
ofono_voicecall_cb_t cb;
|
ofono_voicecall_cb_t cb;
|
||||||
@@ -71,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);
|
||||||
|
|
||||||
@@ -387,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,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) {
|
||||||
@@ -458,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.");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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->cb = NULL;
|
||||||
vd->data = NULL;
|
vd->data = NULL;
|
||||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
cb(ril_error_failure(&error), cbdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,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 {
|
||||||
@@ -618,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);
|
||||||
@@ -636,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;
|
||||||
@@ -824,6 +815,7 @@ 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) {
|
if (modem->ecclist_file) {
|
||||||
@@ -836,17 +828,11 @@ 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);
|
||||||
@@ -855,10 +841,12 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
|
|||||||
ril_ecclist_remove_handler(vd->ecclist, vd->ecclist_change_id);
|
ril_ecclist_remove_handler(vd->ecclist, vd->ecclist_change_id);
|
||||||
ril_ecclist_unref(vd->ecclist);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
@@ -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);
|
||||||
@@ -247,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>
|
||||||
|
#include <gutil_log.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#define DEBUGLOG_PATH "/"
|
#define DEBUGLOG_PATH "/"
|
||||||
#define DEBUGLOG_CHANGED_SIGNAL "Changed"
|
|
||||||
|
|
||||||
static DBusConnection *connection = NULL;
|
enum _debug_server_event {
|
||||||
|
DEBUG_EVENT_CATEGORY_ENABLED,
|
||||||
|
DEBUG_EVENT_CATEGORY_DISABLED,
|
||||||
|
DEBUG_EVENT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
extern struct ofono_debug_desc __start___debug[];
|
static DBusLogServer *debuglog_server;
|
||||||
extern struct ofono_debug_desc __stop___debug[];
|
static GLogProc2 debuglog_default_log_proc;
|
||||||
|
static gulong debuglog_event_id[DEBUG_EVENT_COUNT];
|
||||||
|
|
||||||
static void debuglog_signal(DBusConnection *conn, const char *name,
|
static void debuglog_ofono_log_hook(const struct ofono_debug_desc *desc,
|
||||||
guint flags)
|
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,
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phonebook->pending) {
|
||||||
|
phonebook->pending = g_slist_append(phonebook->pending,
|
||||||
|
dbus_message_ref(msg));
|
||||||
|
} else {
|
||||||
|
phonebook->pending = g_slist_append(NULL,
|
||||||
|
dbus_message_ref(msg));
|
||||||
g_string_set_size(phonebook->vcards, 0);
|
g_string_set_size(phonebook->vcards, 0);
|
||||||
phonebook->storage_index = 0;
|
phonebook->storage_index = 0;
|
||||||
|
|
||||||
phonebook->pending = dbus_message_ref(msg);
|
|
||||||
export_phonebook(phonebook);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1710,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;
|
||||||
}
|
}
|
||||||
@@ -1764,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;
|
||||||
}
|
}
|
||||||
@@ -2314,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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ 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.6
|
Requires: libglibutil >= 1.0.10
|
||||||
Requires(preun): systemd
|
Requires(preun): systemd
|
||||||
Requires(post): systemd
|
Requires(post): systemd
|
||||||
Requires(postun): systemd
|
Requires(postun): systemd
|
||||||
@@ -21,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(libgrilio) >= 1.0.6
|
BuildRequires: pkgconfig(libgrilio) >= 1.0.10
|
||||||
BuildRequires: pkgconfig(libglibutil) >= 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
|
||||||
@@ -69,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"
|
||||||
|
|
||||||
@@ -86,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