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/cdma-provision.h include/handsfree.h \
|
||||
include/handsfree-audio.h \
|
||||
include/sim-mnclength.h include/oemraw.h \
|
||||
include/sim-mnclength.h \
|
||||
include/siri.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_settings.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_data.c \
|
||||
drivers/ril/ril_devinfo.c \
|
||||
@@ -616,7 +619,7 @@ builtin_cflags += @WSPCODEC_CFLAGS@
|
||||
builtin_libadd += @WSPCODEC_LIBS@
|
||||
endif
|
||||
|
||||
if LOGCONTROL
|
||||
if DEBUGLOG
|
||||
builtin_modules += debuglog
|
||||
builtin_sources += plugins/debuglog.c
|
||||
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-provision.c src/handsfree.c \
|
||||
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_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
|
||||
@@ -252,10 +252,16 @@ if (test "${enable_pushforwarder}" != "no"); then
|
||||
AC_SUBST(WSPCODEC_LIBS)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(logcontrol,
|
||||
AC_HELP_STRING([--enable-logcontrol], [enable log control plugin]),
|
||||
[enable_logcontrol=${enableval}], [enable_logcontrol="no"])
|
||||
AM_CONDITIONAL(LOGCONTROL, test "${enable_logcontrol}" != "no")
|
||||
AC_ARG_ENABLE(debuglog,
|
||||
AC_HELP_STRING([--enable-debuglog], [enable log control plugin]),
|
||||
[enable_debuglog=${enableval}], [enable_debuglog="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
|
||||
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
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
#define RIL_REQUEST_GET_SIM_STATUS 1
|
||||
#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 *pending_req;
|
||||
|
||||
enum ril_data_allow_data_opt allow_data;
|
||||
char *log_prefix;
|
||||
guint query_id;
|
||||
gulong io_event_id;
|
||||
@@ -158,6 +159,7 @@ struct ril_data_request_setup {
|
||||
char *password;
|
||||
enum ofono_gprs_proto proto;
|
||||
enum ofono_gprs_auth_method auth_method;
|
||||
int retry_count;
|
||||
};
|
||||
|
||||
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 *call = NULL;
|
||||
|
||||
ril_data_request_completed(req);
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
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 (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
|
||||
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_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io)
|
||||
GRilIoChannel *io, enum ril_data_allow_data_opt opt)
|
||||
{
|
||||
GASSERT(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;
|
||||
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]) ?
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* RIL_VERSION in ril.h was 10 when RIL_REQUEST_ALLOW_DATA first
|
||||
* appeared there.
|
||||
*/
|
||||
if (priv->io->ril_version >= 10) {
|
||||
|
||||
if (priv->allow_data == RIL_ALLOW_DATA_ON) {
|
||||
ril_data_request_queue(ril_data_allow_new(data));
|
||||
} else {
|
||||
priv->flags |= RIL_DATA_FLAG_ON;
|
||||
|
||||
@@ -54,6 +54,12 @@ enum ril_data_manager_flags {
|
||||
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
|
||||
};
|
||||
|
||||
enum ril_data_allow_data_opt {
|
||||
RIL_ALLOW_DATA_AUTO,
|
||||
RIL_ALLOW_DATA_ON,
|
||||
RIL_ALLOW_DATA_OFF
|
||||
};
|
||||
|
||||
enum ril_data_role {
|
||||
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
||||
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
||||
@@ -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_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);
|
||||
void ril_data_unref(struct ril_data *data);
|
||||
gboolean ril_data_allowed(struct ril_data *data);
|
||||
|
||||
@@ -38,7 +38,7 @@ enum ril_ecclist_signal {
|
||||
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 };
|
||||
|
||||
|
||||
@@ -141,16 +141,28 @@ static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
||||
if (gcd->active_call) {
|
||||
ril_gprs_context_free_active_call(gcd);
|
||||
if (gcd->deactivate.req) {
|
||||
/* Complete the deactivate request */
|
||||
ofono_gprs_context_cb_t cb = gcd->deactivate.cb;
|
||||
gpointer data = gcd->deactivate.data;
|
||||
struct ril_gprs_context_call deact = gcd->deactivate;
|
||||
|
||||
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));
|
||||
if (cb) {
|
||||
ril_data_request_cancel(deact.req);
|
||||
if (deact.cb) {
|
||||
struct ofono_error error;
|
||||
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;
|
||||
gpointer cb_data;
|
||||
|
||||
ofono_info("setting up data call");
|
||||
|
||||
ril_error_init_failure(&error);
|
||||
if (ril_status != RIL_E_SUCCESS) {
|
||||
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;
|
||||
}
|
||||
|
||||
ofono_info("setting up data call");
|
||||
|
||||
/* Check the ip address */
|
||||
ril_gprs_split_ip_by_protocol(call->addresses, &split_ip_addr,
|
||||
&split_ipv6_addr);
|
||||
@@ -624,7 +636,15 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
||||
DBG("");
|
||||
ofono_gprs_context_set_data(gc, NULL);
|
||||
|
||||
ril_data_request_cancel(gcd->activate.req);
|
||||
if (gcd->activate.req) {
|
||||
/*
|
||||
* The core has already completed its pending D-Bus
|
||||
* request, invoking the completion callback will
|
||||
* cause libdbus to panic.
|
||||
*/
|
||||
ril_data_request_detach(gcd->activate.req);
|
||||
ril_data_request_cancel(gcd->activate.req);
|
||||
}
|
||||
|
||||
if (gcd->deactivate.req) {
|
||||
/* Let it complete but we won't be around to be notified. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -14,118 +14,251 @@
|
||||
*/
|
||||
|
||||
#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 <gdbus.h>
|
||||
|
||||
/* <mce/dbus-names.h> */
|
||||
#define MCE_SERVICE "com.nokia.mce"
|
||||
#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_DIM_STRING "dimmed"
|
||||
#define MCE_DISPLAY_ON_STRING "on"
|
||||
#define MCE_DISPLAY_OFF_STRING "off"
|
||||
|
||||
struct ril_mce {
|
||||
typedef GObjectClass RilMceClass;
|
||||
typedef struct ril_mce RilMce;
|
||||
|
||||
struct ril_mce_priv {
|
||||
GRilIoChannel *io;
|
||||
DBusConnection *conn;
|
||||
int screen_state;
|
||||
DBusPendingCall *req;
|
||||
guint daemon_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 */
|
||||
grilio_request_append_int32(req, on); /* screen on/off */
|
||||
static enum ril_mce_display_state ril_mce_parse_display_state(DBusMessage *msg)
|
||||
{
|
||||
DBusMessageIter it;
|
||||
|
||||
grilio_channel_send_request(mce->io, req, RIL_REQUEST_SCREEN_STATE);
|
||||
grilio_request_unref(req);
|
||||
if (dbus_message_iter_init(msg, &it) &&
|
||||
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,
|
||||
DBusMessage *message, void *user_data)
|
||||
DBusMessage *msg, void *user_data)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
|
||||
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("");
|
||||
}
|
||||
enum ril_mce_display_state state = ril_mce_parse_display_state(msg);
|
||||
|
||||
DBG("%s", ril_mce_display_state_string(state));
|
||||
ril_mce_update_display_state(RIL_MCE(user_data), state);
|
||||
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)
|
||||
{
|
||||
struct ril_mce *mce = user_data;
|
||||
struct ril_mce *self = RIL_MCE(user_data);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
DBG("");
|
||||
if (!mce->signal_watch) {
|
||||
mce->signal_watch = g_dbus_add_signal_watch(conn,
|
||||
if (!priv->req) {
|
||||
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,
|
||||
ril_mce_display_changed, mce, NULL);
|
||||
ril_mce_display_changed, self, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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("");
|
||||
if (mce->signal_watch) {
|
||||
g_dbus_remove_watch(conn, mce->signal_watch);
|
||||
mce->signal_watch = 0;
|
||||
if (priv->signal_watch) {
|
||||
g_dbus_remove_watch(conn, priv->signal_watch);
|
||||
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());
|
||||
mce->io = grilio_channel_ref(io);
|
||||
mce->screen_state = -1;
|
||||
mce->daemon_watch = g_dbus_add_service_watch(mce->conn, MCE_SERVICE,
|
||||
ril_mce_connect, ril_mce_disconnect, mce, NULL);
|
||||
|
||||
return mce;
|
||||
DBG("");
|
||||
priv->daemon_watch = g_dbus_add_service_watch(priv->conn, MCE_SERVICE,
|
||||
ril_mce_connect, ril_mce_disconnect, self, NULL);
|
||||
return self;
|
||||
}
|
||||
|
||||
void ril_mce_free(struct ril_mce *mce)
|
||||
struct ril_mce *ril_mce_ref(struct ril_mce *self)
|
||||
{
|
||||
if (mce) {
|
||||
if (mce->signal_watch) {
|
||||
g_dbus_remove_watch(mce->conn, mce->signal_watch);
|
||||
}
|
||||
if (mce->daemon_watch) {
|
||||
g_dbus_remove_watch(mce->conn, mce->daemon_watch);
|
||||
}
|
||||
dbus_connection_unref(mce->conn);
|
||||
grilio_channel_unref(mce->io);
|
||||
g_free(mce);
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(RIL_MCE(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ril_mce_unref(struct ril_mce *self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(RIL_MCE(self));
|
||||
}
|
||||
}
|
||||
|
||||
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *self,
|
||||
ril_mce_cb_t cb, void *arg)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||
SIGNAL_DISPLAY_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||
}
|
||||
|
||||
void ril_mce_remove_handler(struct ril_mce *self, gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mce_init(struct ril_mce *self)
|
||||
{
|
||||
struct ril_mce_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
RIL_MCE_TYPE, struct ril_mce_priv);
|
||||
|
||||
priv->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static void ril_mce_dispose(GObject *object)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(object);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
if (priv->signal_watch) {
|
||||
g_dbus_remove_watch(priv->conn, priv->signal_watch);
|
||||
priv->signal_watch = 0;
|
||||
}
|
||||
if (priv->daemon_watch) {
|
||||
g_dbus_remove_watch(priv->conn, priv->daemon_watch);
|
||||
priv->daemon_watch = 0;
|
||||
}
|
||||
if (priv->req) {
|
||||
dbus_pending_call_cancel(priv->req);
|
||||
dbus_pending_call_unref(priv->req);
|
||||
}
|
||||
G_OBJECT_CLASS(ril_mce_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void ril_mce_finalize(GObject *object)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(object);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
dbus_connection_unref(priv->conn);
|
||||
G_OBJECT_CLASS(ril_mce_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void ril_mce_class_init(RilMceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = ril_mce_dispose;
|
||||
object_class->finalize = ril_mce_finalize;
|
||||
g_type_class_add_private(klass, sizeof(struct ril_mce_priv));
|
||||
ril_mce_signals[SIGNAL_DISPLAY_STATE_CHANGED] =
|
||||
g_signal_new(SIGNAL_DISPLAY_STATE_CHANGED_NAME,
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -18,8 +18,27 @@
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
struct ril_mce *ril_mce_new(GRilIoChannel *io);
|
||||
void ril_mce_free(struct ril_mce *mce);
|
||||
enum ril_mce_display_state {
|
||||
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 */
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ struct ril_modem_data {
|
||||
char *imei;
|
||||
char *ecclist_file;
|
||||
gboolean pre_sim_done;
|
||||
gboolean devinfo_created;
|
||||
gboolean allow_data;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
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_voicecall_create(modem, 0, RILMODEM_DRIVER, 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_ussd_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,
|
||||
@@ -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 *modem = &md->modem;
|
||||
|
||||
/*
|
||||
* ril_plugin.c must wait until IMEI becomes known before
|
||||
* creating the modem
|
||||
*/
|
||||
GASSERT(slot->imei);
|
||||
|
||||
/* Copy config */
|
||||
modem->config = *slot->config;
|
||||
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, TRUE);
|
||||
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;
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
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_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,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -16,118 +16,147 @@
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_util.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_modem *modem;
|
||||
GRilIoQueue *q;
|
||||
guint timer_id;
|
||||
DBusConnection *conn;
|
||||
char *path;
|
||||
char *log_prefix;
|
||||
};
|
||||
|
||||
struct ril_oem_raw_cbd {
|
||||
ofono_oem_raw_query_cb_t cb;
|
||||
gpointer data;
|
||||
};
|
||||
#define DBG_(oem,fmt,args...) DBG("%s" fmt, (oem)->log_prefix, ##args)
|
||||
|
||||
#define ril_oem_raw_cbd_free g_free
|
||||
|
||||
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,
|
||||
static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
struct ril_oem_raw_cbd *cbd = user_data;
|
||||
DBusMessage *msg = user_data;
|
||||
DBusMessage *reply;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
struct ofono_oem_raw_results result;
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
DBusMessageIter it, array;
|
||||
const guchar* bytes = data;
|
||||
guint i;
|
||||
|
||||
result.data = (void *)data;
|
||||
result.length = len;
|
||||
cbd->cb(ril_error_ok(&error), &result, cbd->data);
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_message_iter_init_append(reply, &it);
|
||||
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 {
|
||||
DBG("error:%d len:%d ", status, len);
|
||||
cbd->cb(ril_error_failure(&error), NULL, cbd->data);
|
||||
DBG("Error %s", ril_error_to_string(ril_status));
|
||||
reply = __ofono_error_failed(msg);
|
||||
}
|
||||
|
||||
__ofono_dbus_pending_reply(&msg, reply);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
|
||||
void *user_data)
|
||||
{
|
||||
DBusMessageIter it;
|
||||
struct ril_oem_raw *oem = user_data;
|
||||
|
||||
dbus_message_iter_init(msg, &it);
|
||||
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
|
||||
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
|
||||
char *data;
|
||||
int data_len;
|
||||
DBusMessageIter array;
|
||||
GRilIoRequest *req;
|
||||
|
||||
/* Fetch the data */
|
||||
dbus_message_iter_recurse(&it, &array);
|
||||
dbus_message_iter_get_fixed_array(&array, &data, &data_len);
|
||||
DBG_(oem, "%d bytes", data_len);
|
||||
|
||||
/*
|
||||
* And forward it to rild. Set a timeout because rild may
|
||||
* never respond to invalid requests.
|
||||
*/
|
||||
req = grilio_request_sized_new(data_len);
|
||||
grilio_request_set_timeout(req, RIL_OEM_RAW_TIMEOUT);
|
||||
grilio_request_append_bytes(req, data, data_len);
|
||||
grilio_queue_send_request_full(oem->q, req,
|
||||
RIL_REQUEST_OEM_HOOK_RAW, ril_oem_raw_send_cb,
|
||||
NULL, dbus_message_ref(msg));
|
||||
grilio_request_unref(req);
|
||||
return NULL;
|
||||
} else {
|
||||
DBG_(oem, "Unexpected signature");
|
||||
return __ofono_error_invalid_args(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_oem_raw_request(struct ofono_oem_raw *raw,
|
||||
const struct ofono_oem_raw_request *request,
|
||||
ofono_oem_raw_query_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
GRilIoRequest *req = grilio_request_sized_new(request->length);
|
||||
|
||||
grilio_request_append_bytes(req, request->data, request->length);
|
||||
grilio_queue_send_request_full(od->q, req, RIL_REQUEST_OEM_HOOK_RAW,
|
||||
ril_oem_raw_request_cb, ril_oem_raw_cbd_free,
|
||||
ril_oem_raw_cbd_new(cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static gboolean ril_oem_raw_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_oem_raw *raw = user_data;
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
GASSERT(od->timer_id);
|
||||
od->timer_id = 0;
|
||||
ofono_oem_raw_dbus_register(raw);
|
||||
|
||||
/* Single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_oem_raw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
struct ril_oem_raw *od = g_new0(struct ril_oem_raw, 1);
|
||||
|
||||
DBG("");
|
||||
od->q = grilio_queue_new(ril_modem_io(modem));
|
||||
od->timer_id = g_idle_add(ril_oem_raw_register, raw);
|
||||
ofono_oem_raw_set_data(raw, od);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_oem_raw_remove(struct ofono_oem_raw *raw)
|
||||
{
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
grilio_queue_cancel_all(od->q, TRUE);
|
||||
ofono_oem_raw_set_data(raw, NULL);
|
||||
|
||||
if (od->timer_id) {
|
||||
g_source_remove(od->timer_id);
|
||||
}
|
||||
|
||||
grilio_queue_unref(od->q);
|
||||
g_free(od);
|
||||
}
|
||||
|
||||
/* const */ struct ofono_oem_raw_driver ril_oem_raw_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_oem_raw_probe,
|
||||
.remove = ril_oem_raw_remove,
|
||||
.request = ril_oem_raw_request,
|
||||
static const GDBusMethodTable ril_oem_raw_methods[] = {
|
||||
{ GDBUS_ASYNC_METHOD("Send",
|
||||
GDBUS_ARGS({ "request", "ay" }),
|
||||
GDBUS_ARGS({ "response", "ay" }),
|
||||
ril_oem_raw_send) },
|
||||
{ }
|
||||
};
|
||||
|
||||
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:
|
||||
* mode: C
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,9 +14,11 @@
|
||||
*/
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_config.h"
|
||||
#include "ril_sim_card.h"
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_sim_settings.h"
|
||||
#include "ril_cell_info.h"
|
||||
#include "ril_network.h"
|
||||
#include "ril_radio.h"
|
||||
#include "ril_data.h"
|
||||
@@ -48,10 +50,10 @@
|
||||
#define RILMODEM_DEFAULT_SLOT 0xffffffff
|
||||
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
|
||||
#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_CONF_GROUP "Settings"
|
||||
#define RILMODEM_CONF_3GHANDOVER "3GLTEHandover"
|
||||
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
|
||||
|
||||
#define RILCONF_DEV_PREFIX "ril_"
|
||||
#define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
|
||||
@@ -63,6 +65,7 @@
|
||||
#define RILCONF_4G "enable4G"
|
||||
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
|
||||
#define RILCONF_ECCLIST_FILE "ecclistFile"
|
||||
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
||||
|
||||
#define RIL_STORE "ril"
|
||||
#define RIL_STORE_GROUP "Settings"
|
||||
@@ -83,6 +86,9 @@ struct ril_plugin_priv {
|
||||
struct ril_plugin pub;
|
||||
struct ril_plugin_dbus *dbus;
|
||||
struct ril_data_manager *data_manager;
|
||||
struct ril_mce *mce;
|
||||
gboolean display_on;
|
||||
gulong display_state_change_id;
|
||||
GSList *slots;
|
||||
ril_slot_info_ptr *slots_info;
|
||||
struct ril_slot *voice_slot;
|
||||
@@ -102,9 +108,10 @@ struct ril_slot {
|
||||
char *sockpath;
|
||||
char *sub;
|
||||
char *ecclist_file;
|
||||
gint timeout; /* RIL timeout, in milliseconds */
|
||||
int timeout; /* RIL timeout, in milliseconds */
|
||||
int index;
|
||||
int sim_flags;
|
||||
enum ril_data_allow_data_opt allow_data_opt;
|
||||
struct ril_slot_config config;
|
||||
struct ril_plugin_priv *plugin;
|
||||
struct ril_modem *modem;
|
||||
@@ -116,6 +123,9 @@ struct ril_slot {
|
||||
struct ril_sim_info *sim_info;
|
||||
struct ril_sim_info_dbus *sim_info_dbus;
|
||||
struct ril_sim_settings *sim_settings;
|
||||
struct ril_cell_info *cell_info;
|
||||
struct ril_cell_info_dbus *cell_info_dbus;
|
||||
struct ril_oem_raw *oem_raw;
|
||||
struct ril_data *data;
|
||||
GRilIoChannel *io;
|
||||
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");
|
||||
|
||||
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 = {
|
||||
.name = "ril_trace",
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT,
|
||||
.name = ril_debug_trace_name,
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||
.notify = ril_debug_trace_notify
|
||||
};
|
||||
|
||||
static struct ofono_debug_desc ril_debug_dump OFONO_DEBUG_ATTR = {
|
||||
.name = "ril_dump",
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT,
|
||||
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||
.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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (kill_io) {
|
||||
if (slot->mce) {
|
||||
ril_mce_free(slot->mce);
|
||||
slot->mce = NULL;
|
||||
}
|
||||
|
||||
if (slot->retry_id) {
|
||||
g_source_remove(slot->retry_id);
|
||||
slot->retry_id = 0;
|
||||
}
|
||||
|
||||
if (slot->cell_info) {
|
||||
ril_cell_info_unref(slot->cell_info);
|
||||
slot->cell_info = NULL;
|
||||
}
|
||||
|
||||
if (slot->data) {
|
||||
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
||||
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) {
|
||||
ril_sim_info_set_network(slot->sim_info, slot->network);
|
||||
ril_network_unref(slot->network);
|
||||
slot->network = NULL;
|
||||
}
|
||||
@@ -488,8 +531,9 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
|
||||
}
|
||||
|
||||
if (plugin->pub.ready != ready) {
|
||||
DBG("%sready", ready ? "" : "not ");
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -643,11 +687,21 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
||||
GASSERT(slot->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) {
|
||||
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
||||
slot->sim_info_dbus = NULL;
|
||||
}
|
||||
|
||||
if (slot->cell_info_dbus) {
|
||||
ril_cell_info_dbus_free(slot->cell_info_dbus);
|
||||
slot->cell_info_dbus = NULL;
|
||||
}
|
||||
|
||||
slot->modem = NULL;
|
||||
ril_radio_set_online(slot->radio, FALSE);
|
||||
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,
|
||||
guint id, guint code, const void *data, guint data_len, void *user_data)
|
||||
{
|
||||
/* Turn prefix off */
|
||||
static GLogModule log_module = {
|
||||
.max_level = GLOG_LEVEL_VERBOSE,
|
||||
.level = GLOG_LEVEL_VERBOSE
|
||||
};
|
||||
|
||||
static const GLogModule* log_module = &ril_debug_trace_module;
|
||||
const char *prefix = io->name ? io->name : "";
|
||||
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
|
||||
const char *scode;
|
||||
@@ -675,21 +724,21 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||
} else {
|
||||
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);
|
||||
break;
|
||||
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));
|
||||
break;
|
||||
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));
|
||||
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 (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 (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 = 0;
|
||||
}
|
||||
ril_debug_dump_update_slot(slot);
|
||||
ril_debug_dump_update(slot);
|
||||
}
|
||||
} else if (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) : "";
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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_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);
|
||||
}
|
||||
|
||||
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,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_slot *slot = user_data;
|
||||
struct ril_plugin_priv *plugin = slot->plugin;
|
||||
gboolean all_done = TRUE;
|
||||
GSList *link;
|
||||
char *imei = NULL;
|
||||
|
||||
GASSERT(!slot->imei);
|
||||
GASSERT(slot->imei_req_id);
|
||||
slot->imei_req_id = 0;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
slot->pub.imei = slot->imei = grilio_parser_get_utf8(&rilp);
|
||||
DBG("%s", slot->imei);
|
||||
if (slot->modem) {
|
||||
ril_modem_set_imei(slot->modem, slot->imei);
|
||||
}
|
||||
ril_plugin_update_ready(plugin);
|
||||
imei = grilio_parser_get_utf8(&rilp);
|
||||
|
||||
DBG("%s", imei);
|
||||
|
||||
/*
|
||||
* slot->imei should be either NULL (when we get connected
|
||||
* to rild the very first time) or match the already known
|
||||
* IMEI (if rild crashed and we have reconnected)
|
||||
*/
|
||||
GASSERT(!slot->imei || !g_strcmp0(slot->imei, imei));
|
||||
} else {
|
||||
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
|
||||
ril_error_to_string(status));
|
||||
}
|
||||
|
||||
for (link = plugin->slots; link && all_done; link = link->next) {
|
||||
if (((struct ril_slot *)link->data)->imei_req_id) {
|
||||
all_done = FALSE;
|
||||
}
|
||||
}
|
||||
g_free(slot->imei);
|
||||
slot->pub.imei = slot->imei = (imei ? imei : g_strdup("ERROR"));
|
||||
|
||||
if (all_done) {
|
||||
DBG("all done");
|
||||
ril_plugin_dbus_block_imei_requests(plugin->dbus, FALSE);
|
||||
}
|
||||
ril_plugin_check_modem(slot);
|
||||
ril_plugin_update_ready(slot->plugin);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -842,6 +901,7 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||
{
|
||||
struct ril_plugin_priv *plugin = slot->plugin;
|
||||
const char *log_prefix = ril_plugin_log_prefix(slot);
|
||||
GRilIoRequest* req;
|
||||
|
||||
ofono_debug("%s version %u", (slot->name && slot->name[0]) ?
|
||||
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_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);
|
||||
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);
|
||||
grilio_request_unref(req);
|
||||
|
||||
GASSERT(!slot->radio);
|
||||
slot->radio = ril_radio_new(slot->io);
|
||||
@@ -874,15 +941,20 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||
GASSERT(!slot->network);
|
||||
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
|
||||
slot->sim_card, slot->sim_settings);
|
||||
ril_sim_info_set_network(slot->sim_info, slot->network);
|
||||
|
||||
GASSERT(!slot->data);
|
||||
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) {
|
||||
ril_plugin_create_modem(slot);
|
||||
GASSERT(!slot->cell_info);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -900,8 +972,8 @@ static void ril_plugin_init_io(struct ril_slot *slot)
|
||||
DBG("%s %s", slot->sockpath, slot->sub);
|
||||
slot->io = grilio_channel_new_socket(slot->sockpath, slot->sub);
|
||||
if (slot->io) {
|
||||
ril_debug_trace_update_slot(slot);
|
||||
ril_debug_dump_update_slot(slot);
|
||||
ril_debug_trace_update(slot);
|
||||
ril_debug_dump_update(slot);
|
||||
|
||||
if (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->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||
list = g_slist_append(list, slot);
|
||||
|
||||
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->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||
slot->config.slot = 1;
|
||||
list = g_slist_append(list, slot);
|
||||
} else {
|
||||
@@ -993,6 +1067,7 @@ static GSList *ril_plugin_create_default_config()
|
||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||
list = g_slist_append(list, slot);
|
||||
}
|
||||
} else {
|
||||
@@ -1002,20 +1077,6 @@ static GSList *ril_plugin_create_default_config()
|
||||
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,
|
||||
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);
|
||||
if (sock) {
|
||||
int value;
|
||||
GError *err = NULL;
|
||||
char *sub = g_key_file_get_string(file, group, RILCONF_SUB,
|
||||
NULL);
|
||||
char* strval;
|
||||
char *sub = ril_config_get_string(file, group, RILCONF_SUB);
|
||||
|
||||
slot = g_new0(struct ril_slot, 1);
|
||||
slot->sockpath = sock;
|
||||
slot->path = g_strconcat("/", group, NULL);
|
||||
slot->name = g_key_file_get_string(file, group, RILCONF_NAME,
|
||||
NULL);
|
||||
slot->name = ril_config_get_string(file, group, RILCONF_NAME);
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||
|
||||
if (sub && strlen(sub) == RIL_SUB_SIZE) {
|
||||
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);
|
||||
}
|
||||
|
||||
value = g_key_file_get_integer(file, group, RILCONF_SLOT, &err);
|
||||
if (!err && value >= 0) {
|
||||
if (ril_config_get_integer(file, group, RILCONF_SLOT, &value) &&
|
||||
value >= 0) {
|
||||
slot->config.slot = value;
|
||||
DBG("%s: slot %u", group, slot->config.slot);
|
||||
} else {
|
||||
slot->config.slot = RILMODEM_DEFAULT_SLOT;
|
||||
if (err) {
|
||||
g_error_free(err);
|
||||
err = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
value = g_key_file_get_integer(file, group, RILCONF_TIMEOUT,
|
||||
&err);
|
||||
if (!err) {
|
||||
slot->timeout = value;
|
||||
if (ril_config_get_integer(file, group, RILCONF_TIMEOUT,
|
||||
&slot->timeout)) {
|
||||
DBG("%s: timeout %d", group, slot->timeout);
|
||||
} else {
|
||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
if (err) {
|
||||
g_error_free(err);
|
||||
err = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
slot->config.enable_4g = g_key_file_get_boolean(file, group,
|
||||
RILCONF_4G, &err);
|
||||
if (err) {
|
||||
/* Set to default */
|
||||
if (!ril_config_get_boolean(file, group, RILCONF_4G,
|
||||
&slot->config.enable_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");
|
||||
|
||||
ril_plugin_read_config_flag(file, group,
|
||||
ril_config_get_flag(file, group,
|
||||
RILCONF_UICC_WORKAROUND,
|
||||
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
|
||||
&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) ?
|
||||
"on" : "off");
|
||||
|
||||
slot->ecclist_file = g_key_file_get_string(file, group,
|
||||
RILCONF_ECCLIST_FILE, NULL);
|
||||
strval = ril_config_get_string(file, group,
|
||||
RILCONF_ALLOW_DATA_REQ);
|
||||
if (strval) {
|
||||
slot->allow_data_opt =
|
||||
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
|
||||
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
|
||||
RIL_ALLOW_DATA_AUTO;
|
||||
g_free(strval);
|
||||
}
|
||||
DBG("%s: AllowDataReq %s", group,
|
||||
(slot->allow_data_opt == RIL_ALLOW_DATA_ON) ? "on" :
|
||||
(slot->allow_data_opt == RIL_ALLOW_DATA_OFF) ? "off" :
|
||||
"auto");
|
||||
|
||||
slot->ecclist_file = ril_config_get_string(file, group,
|
||||
RILCONF_ECCLIST_FILE);
|
||||
if (slot->ecclist_file && slot->ecclist_file[0]) {
|
||||
DBG("%s: ecclist file %s", group, slot->ecclist_file);
|
||||
slot->pub.ecclist_file = slot->ecclist_file;
|
||||
@@ -1171,10 +1231,10 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
|
||||
if (slot) {
|
||||
list = ril_plugin_add_slot(list, slot);
|
||||
}
|
||||
} else if (!strcmp(group, RILMODEM_CONF_GROUP)) {
|
||||
} else if (!strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||
/* Plugin configuration */
|
||||
ril_plugin_read_config_flag(file, group,
|
||||
RILMODEM_CONF_3GHANDOVER,
|
||||
ril_config_get_flag(file, group,
|
||||
RILCONF_SETTINGS_3GHANDOVER,
|
||||
RIL_DATA_MANAGER_3GLTE_HANDOVER,
|
||||
&ps->dm_flags);
|
||||
}
|
||||
@@ -1256,9 +1316,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
|
||||
{
|
||||
if (slot->pub.enabled) {
|
||||
DBG("%s enabled", slot->path + 1);
|
||||
if (ril_plugin_can_create_modem(slot) && !slot->modem) {
|
||||
ril_plugin_create_modem(slot);
|
||||
}
|
||||
ril_plugin_check_modem(slot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1441,7 +1499,7 @@ static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
||||
slot->plugin = plugin;
|
||||
slot->pub.path = slot->path;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1459,19 +1517,19 @@ static void ril_plugin_enable_slot(struct ril_slot *slot)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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("");
|
||||
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;
|
||||
|
||||
ril_plugin_switch_user();
|
||||
@@ -1508,6 +1581,9 @@ static int ril_plugin_init(void)
|
||||
ril_plugin_init_slots(ril_plugin);
|
||||
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
|
||||
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) {
|
||||
/*
|
||||
@@ -1564,7 +1640,6 @@ static int ril_plugin_init(void)
|
||||
ofono_phonebook_driver_register(&ril_phonebook_driver);
|
||||
ofono_ussd_driver_register(&ril_ussd_driver);
|
||||
ofono_cbs_driver_register(&ril_cbs_driver);
|
||||
ofono_oem_raw_driver_register(&ril_oem_raw_driver);
|
||||
ofono_stk_driver_register(&ril_stk_driver);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Set initial screen state and register for updates */
|
||||
ril_plugin_foreach_slot(ril_plugin, ril_plugin_send_screen_state);
|
||||
ril_plugin->display_state_change_id =
|
||||
ril_mce_add_display_state_changed_handler(ril_plugin->mce,
|
||||
ril_plugin_display_state_cb, ril_plugin);
|
||||
|
||||
/* This will set 'ready' flag if we have no modems at all */
|
||||
ril_plugin_update_ready(ril_plugin);
|
||||
return 0;
|
||||
@@ -1602,13 +1683,15 @@ static void ril_plugin_exit(void)
|
||||
ofono_phonebook_driver_unregister(&ril_phonebook_driver);
|
||||
ofono_ussd_driver_unregister(&ril_ussd_driver);
|
||||
ofono_cbs_driver_unregister(&ril_cbs_driver);
|
||||
ofono_oem_raw_driver_unregister(&ril_oem_raw_driver);
|
||||
ofono_stk_driver_unregister(&ril_stk_driver);
|
||||
|
||||
if (ril_plugin) {
|
||||
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
|
||||
ril_plugin_dbus_free(ril_plugin->dbus);
|
||||
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_free(ril_plugin->slots_info);
|
||||
g_free(ril_plugin->default_voice_imsi);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <ofono/gprs-context.h>
|
||||
#include <ofono/gprs.h>
|
||||
#include <ofono/netreg.h>
|
||||
#include <ofono/oemraw.h>
|
||||
#include <ofono/phonebook.h>
|
||||
#include <ofono/radio-settings.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,
|
||||
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 *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_sim_info *info);
|
||||
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus);
|
||||
|
||||
struct ril_cell_info_dbus;
|
||||
struct ril_cell_info_dbus *ril_cell_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_cell_info *info);
|
||||
void ril_cell_info_dbus_free(struct ril_cell_info_dbus *dbus);
|
||||
|
||||
struct ril_plugin_dbus;
|
||||
struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin);
|
||||
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_data *data, struct ril_sim_settings *settings);
|
||||
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_gprs *ril_modem_ofono_gprs(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_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_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_modem_driver ril_modem_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_radio_settings_driver ril_radio_settings_driver;
|
||||
extern const struct ofono_sim_driver ril_sim_driver;
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
struct ril_sim {
|
||||
GRilIoChannel *io;
|
||||
GRilIoQueue *q;
|
||||
GRilIoQueue *q2;
|
||||
GList *pin_cbd_list;
|
||||
struct ofono_sim *sim;
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
const unsigned char *path, unsigned int 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->q, fileid, path, len, cb, 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
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->q, fileid, start, 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);
|
||||
ril_sim_read(sd, sd->q, fileid, CMD_READ_BINARY, (start >> 8),
|
||||
(start & 0xff), length, path, path_len, cb, data);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
int rec, int length, const unsigned char *path,
|
||||
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));
|
||||
grilio_request_append_int32(req, GET_IMSI_NUM_PARAMS);
|
||||
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,
|
||||
ril_sim_get_imsi_cb, ril_sim_cbd_free,
|
||||
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->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
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->q2 = grilio_queue_new(sd->io);
|
||||
|
||||
DBG("[%u]", sd->slot);
|
||||
|
||||
@@ -1077,7 +1008,6 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
DBG("[%u]", sd->slot);
|
||||
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->q2, TRUE);
|
||||
ofono_sim_set_data(sim, NULL);
|
||||
|
||||
if (sd->idle_id) {
|
||||
@@ -1093,7 +1023,6 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
|
||||
grilio_channel_unref(sd->io);
|
||||
grilio_queue_unref(sd->q);
|
||||
grilio_queue_unref(sd->q2);
|
||||
g_free(sd);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_network.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <ofono/sim.h>
|
||||
@@ -29,10 +30,15 @@
|
||||
#define RIL_SIM_ICCID_MAP "iccidmap"
|
||||
#define RIL_SIM_ICCID_MAP_IMSI "imsi"
|
||||
|
||||
#define RIL_SIM_DEFAULT_SPN_BUFSIZE 8
|
||||
G_STATIC_ASSERT(RIL_SIM_DEFAULT_SPN_BUFSIZE >= \
|
||||
OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1);
|
||||
|
||||
typedef GObjectClass RilSimInfoClass;
|
||||
typedef struct ril_sim_info RilSimInfo;
|
||||
|
||||
typedef void (*ril_sim_info_remove_cb_t)(struct ofono_sim *sim, unsigned int id);
|
||||
typedef void (*ril_sim_info_remove_cb_t)(struct ofono_sim *sim,
|
||||
unsigned int id);
|
||||
typedef void (*ril_sim_info_set_value_cb_t)(struct ril_sim_info *info,
|
||||
const char *value);
|
||||
|
||||
@@ -44,14 +50,20 @@ struct ril_sim_info_watch {
|
||||
};
|
||||
|
||||
struct ril_sim_info_priv {
|
||||
char *log_prefix;
|
||||
char *iccid;
|
||||
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 ril_sim_info_watch state_watch;
|
||||
struct ril_sim_info_watch iccid_watch;
|
||||
struct ril_sim_info_watch imsi_watch;
|
||||
struct ril_sim_info_watch spn_watch;
|
||||
struct ril_network *network;
|
||||
gulong network_operator_changed_id;
|
||||
gboolean update_imsi_cache;
|
||||
gboolean update_iccid_map;
|
||||
};
|
||||
@@ -80,6 +92,8 @@ G_DEFINE_TYPE(RilSimInfo, ril_sim_info, G_TYPE_OBJECT)
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||
|
||||
#define DBG_(info,fmt,args...) DBG("%s" fmt, (info)->priv->log_prefix, ##args)
|
||||
|
||||
static void ril_sim_info_signal_emit(struct ril_sim_info *self,
|
||||
enum ril_sim_info_signal id)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
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;
|
||||
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);
|
||||
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
||||
RIL_SIM_INFO_STORE_SPN, priv->spn);
|
||||
storage_close(priv->imsi, store, cache, TRUE);
|
||||
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||
save = TRUE;
|
||||
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
||||
RIL_SIM_INFO_STORE_SPN, priv->cached_spn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we are most likely running on flash which
|
||||
* supports a limited number of writes, don't overwrite
|
||||
* the file unless something has actually changed.
|
||||
*/
|
||||
if (save) {
|
||||
DBG_(self, "updating " STORAGEDIR "/%s/%s",
|
||||
priv->imsi, store);
|
||||
storage_close(priv->imsi, store, cache, TRUE);
|
||||
} else {
|
||||
g_key_file_free(cache);
|
||||
}
|
||||
|
||||
g_free(spn);
|
||||
priv->update_imsi_cache = FALSE;
|
||||
}
|
||||
}
|
||||
@@ -135,11 +170,24 @@ static void ril_sim_info_update_iccid_map(struct ril_sim_info *self)
|
||||
priv->imsi && priv->imsi[0]) {
|
||||
const char *store = RIL_SIM_ICCID_MAP;
|
||||
GKeyFile *map = storage_open(NULL, store);
|
||||
char *imsi = g_key_file_get_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||
priv->iccid, NULL);
|
||||
|
||||
DBG("Updating " STORAGEDIR "/%s", store);
|
||||
g_key_file_set_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||
/*
|
||||
* Since we are most likely running on flash which
|
||||
* supports a limited number of writes, don't overwrite
|
||||
* the file unless something has actually changed.
|
||||
*/
|
||||
if (g_strcmp0(imsi, priv->imsi)) {
|
||||
DBG_(self, "updating " STORAGEDIR "/%s", store);
|
||||
g_key_file_set_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||
priv->iccid, priv->imsi);
|
||||
storage_close(NULL, store, map, TRUE);
|
||||
storage_close(NULL, store, map, TRUE);
|
||||
} else {
|
||||
g_key_file_free(map);
|
||||
}
|
||||
|
||||
g_free(imsi);
|
||||
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;
|
||||
|
||||
if (g_strcmp0(priv->spn, spn)) {
|
||||
g_free(priv->spn);
|
||||
self->spn = priv->spn = g_strdup(spn);
|
||||
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||
DBG_(self, "cached spn \"%s\"", spn);
|
||||
g_free(priv->cached_spn);
|
||||
priv->cached_spn = g_strdup(spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
ril_sim_info_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)
|
||||
{
|
||||
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 (priv->imsi && priv->imsi[0]) {
|
||||
/* 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;
|
||||
}
|
||||
g_free(priv->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_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||
} else if (imsi) {
|
||||
g_free(imsi);
|
||||
} 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);
|
||||
g_key_file_free(cache);
|
||||
|
||||
if (spn && spn[0] && g_strcmp0(priv->spn, spn)) {
|
||||
if (priv->spn && priv->spn[0]) {
|
||||
if (spn && spn[0] && g_strcmp0(priv->cached_spn, spn)) {
|
||||
if (priv->cached_spn && priv->cached_spn[0]) {
|
||||
/* Need to update the cache file */
|
||||
DBG("spn changing %s -> %s", priv->spn, spn);
|
||||
DBG_(self, "spn changing %s -> %s",
|
||||
priv->cached_spn, spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
}
|
||||
g_free(priv->spn);
|
||||
self->spn = priv->spn = spn;
|
||||
DBG("spn[%s] = \"%s\"", priv->imsi, spn);
|
||||
g_free(priv->cached_spn);
|
||||
priv->cached_spn = spn;
|
||||
DBG_(self, "spn[%s] = \"%s\"", priv->imsi, spn);
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||
ril_sim_info_update_public_spn(self);
|
||||
} else if (spn) {
|
||||
g_free(spn);
|
||||
} 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)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
DBG("%s", imsi);
|
||||
|
||||
DBG_(watch->info, "%s", 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
DBG("%s", iccid);
|
||||
|
||||
DBG_(watch->info, "%s", 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_watch *watch;
|
||||
|
||||
DBG("%d", state);
|
||||
DBG_(self, "%d", state);
|
||||
|
||||
switch (state) {
|
||||
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);
|
||||
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,
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
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,
|
||||
ril_sim_info_watch_done);
|
||||
GASSERT(priv->state_watch.id);
|
||||
DBG("Attached to sim");
|
||||
DBG_(self, "attached to sim");
|
||||
ril_sim_info_handle_sim_state(self,
|
||||
ofono_sim_get_state(sim));
|
||||
}
|
||||
|
||||
ril_sim_info_network_check(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ril_sim_info_set_network(struct ril_sim_info *self,
|
||||
struct ril_network *network)
|
||||
{
|
||||
if (G_LIKELY(self) && self->priv->network != network) {
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->network) {
|
||||
ril_network_remove_handlers(priv->network,
|
||||
&priv->network_operator_changed_id, 1);
|
||||
ril_network_unref(priv->network);
|
||||
}
|
||||
if (network) {
|
||||
priv->network_operator_changed_id =
|
||||
ril_network_add_operator_changed_handler(network,
|
||||
ril_sim_info_network_operator_changed,
|
||||
self);
|
||||
priv->network = ril_network_ref(network);
|
||||
ril_sim_info_network_check(self);
|
||||
} else {
|
||||
priv->network = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,14 +599,14 @@ static void ril_sim_info_init(struct ril_sim_info *self)
|
||||
RIL_SIMINFO_TYPE, struct ril_sim_info_priv);
|
||||
|
||||
self->priv = priv;
|
||||
ril_sim_info_watch_init(self, &priv->state_watch, NULL,
|
||||
ofono_sim_remove_state_watch);
|
||||
ril_sim_info_watch_init(self, &priv->iccid_watch, ril_sim_info_set_iccid,
|
||||
ofono_sim_remove_iccid_watch);
|
||||
ril_sim_info_watch_init(self, &priv->imsi_watch, ril_sim_info_set_imsi,
|
||||
ofono_sim_remove_imsi_watch);
|
||||
ril_sim_info_watch_init(self, &priv->spn_watch, ril_sim_info_set_spn,
|
||||
ril_sim_info_remove_spn_watch);
|
||||
ril_sim_info_watch_init(self, &priv->state_watch,
|
||||
NULL, ofono_sim_remove_state_watch);
|
||||
ril_sim_info_watch_init(self, &priv->iccid_watch,
|
||||
ril_sim_info_set_iccid, ofono_sim_remove_iccid_watch);
|
||||
ril_sim_info_watch_init(self, &priv->imsi_watch,
|
||||
ril_sim_info_set_imsi, ofono_sim_remove_imsi_watch);
|
||||
ril_sim_info_watch_init(self, &priv->spn_watch,
|
||||
ril_sim_info_set_sim_spn, ril_sim_info_remove_spn_watch);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dispose(GObject *object)
|
||||
@@ -437,14 +614,30 @@ static void ril_sim_info_dispose(GObject *object)
|
||||
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||
|
||||
ril_sim_info_set_ofono_sim(self, NULL);
|
||||
ril_sim_info_set_network(self, NULL);
|
||||
G_OBJECT_CLASS(ril_sim_info_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void ril_sim_info_finalize(GObject *object)
|
||||
{
|
||||
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
g_free(priv->log_prefix);
|
||||
g_free(priv->cached_spn);
|
||||
g_free(priv->public_spn);
|
||||
GASSERT(!priv->iccid);
|
||||
GASSERT(!priv->imsi);
|
||||
GASSERT(!priv->sim_spn);
|
||||
G_OBJECT_CLASS(ril_sim_info_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void ril_sim_info_class_init(RilSimInfoClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = ril_sim_info_dispose;
|
||||
object_class->finalize = ril_sim_info_finalize;
|
||||
g_type_class_add_private(klass, sizeof(struct ril_sim_info_priv));
|
||||
NEW_SIGNAL(klass, ICCID);
|
||||
NEW_SIGNAL(klass, IMSI);
|
||||
|
||||
@@ -29,10 +29,11 @@ struct ril_sim_info {
|
||||
struct ofono_sim;
|
||||
typedef void (*ril_sim_info_cb_t)(struct ril_sim_info *info, void *arg);
|
||||
|
||||
struct ril_sim_info *ril_sim_info_new(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);
|
||||
void ril_sim_info_unref(struct ril_sim_info *si);
|
||||
void ril_sim_info_set_ofono_sim(struct ril_sim_info *si, struct ofono_sim *sim);
|
||||
void ril_sim_info_set_network(struct ril_sim_info *si, struct ril_network *net);
|
||||
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *si,
|
||||
ril_sim_info_cb_t cb, void *arg);
|
||||
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *si,
|
||||
|
||||
@@ -205,7 +205,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
|
||||
return dbus;
|
||||
} else {
|
||||
ofono_error("RIL D-Bus register failed");
|
||||
ofono_error("CellInfo D-Bus register failed");
|
||||
ril_sim_info_dbus_free(dbus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -22,13 +22,16 @@
|
||||
#include "util.h"
|
||||
#include "simutil.h"
|
||||
|
||||
#define RIL_SMS_ACK_RETRY_MS 1000
|
||||
#define RIL_SMS_ACK_RETRY_COUNT 10
|
||||
|
||||
#define SIM_EFSMS_FILEID 0x6F3C
|
||||
#define EFSMS_LENGTH 176
|
||||
|
||||
#define TYPE_LOCAL 129
|
||||
#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 {
|
||||
SMS_EVENT_NEW_SMS,
|
||||
@@ -42,6 +45,7 @@ struct ril_sms {
|
||||
GRilIoQueue *q;
|
||||
struct ril_modem *modem;
|
||||
struct ofono_sms *sms;
|
||||
struct ofono_sim_context *sim_context;
|
||||
gulong event_id[SMS_EVENT_COUNT];
|
||||
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 */
|
||||
|
||||
/* 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,
|
||||
RIL_REQUEST_SMS_ACKNOWLEDGE, ril_ack_delivery_cb, NULL, NULL);
|
||||
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);
|
||||
}
|
||||
|
||||
static void ril_sms_on_sim_cb(const struct ofono_error *error,
|
||||
const unsigned char *sdata,
|
||||
int length, void *data)
|
||||
static void ril_sms_on_sim_cb(int ok, int total_length, int record,
|
||||
const unsigned char *sdata, int length, void *userdata)
|
||||
{
|
||||
struct ril_sms_on_sim_req *cbd = data;
|
||||
struct ril_sms_on_sim_req *cbd = userdata;
|
||||
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
|
||||
* to calculate the proper tpdu length.
|
||||
*/
|
||||
if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
if (ok) {
|
||||
unsigned int smsc_len = sdata[1] + 1;
|
||||
ofono_sms_deliver_notify(sd->sms, sdata + 1, length - 1,
|
||||
length - smsc_len - 1);
|
||||
@@ -409,10 +414,15 @@ static void ril_sms_on_sim(GRilIoChannel *io, guint ril_event,
|
||||
grilio_parser_get_int32(&rilp, &data_len) && data_len > 0 &&
|
||||
grilio_parser_get_int32(&rilp, &rec)) {
|
||||
DBG("rec %d", rec);
|
||||
ril_sim_read_file_linear(sim, SIM_EFSMS_FILEID, rec,
|
||||
EFSMS_LENGTH, path, sizeof(path),
|
||||
ril_sms_on_sim_cb,
|
||||
ril_sms_on_sim_req_new(sd,rec));
|
||||
if (sd->sim_context) {
|
||||
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_req_new(sd,rec));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,14 +454,18 @@ static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
|
||||
void *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);
|
||||
|
||||
sd->modem = modem;
|
||||
sd->sms = sms;
|
||||
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->timer_id = g_idle_add(ril_sms_register, sd);
|
||||
ofono_sms_set_data(sms, sd);
|
||||
|
||||
GASSERT(sd->sim_context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -463,6 +477,10 @@ static void ril_sms_remove(struct ofono_sms *sms)
|
||||
DBG("");
|
||||
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++) {
|
||||
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
|
||||
#
|
||||
@@ -6,6 +6,10 @@
|
||||
# common settings are in the [Settings] section, all other sections
|
||||
# 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]
|
||||
|
||||
@@ -83,3 +87,11 @@ socket=/dev/socket/rild
|
||||
# chmod 0644 /var/lib/ofono/ril.ecclist
|
||||
#
|
||||
#ecclistFile=/var/lib/ofono/ril.ecclist
|
||||
|
||||
# RIL_REQUEST_ALLOW_DATA may or may not be supported by your RIL.
|
||||
# This option allows you to forcibly enable or disable use of this request.
|
||||
# Possible values are auto, on and off
|
||||
#
|
||||
# Default is auto (usage based on the RIL version)
|
||||
#
|
||||
#allowDataReq=auto
|
||||
|
||||
@@ -39,6 +39,7 @@ struct ofono_sim;
|
||||
#define RIL_RETRY_SECS (2)
|
||||
#define RIL_RETRY_MS (RIL_RETRY_SECS*1000)
|
||||
|
||||
struct ril_mce;
|
||||
struct ril_data;
|
||||
struct ril_modem;
|
||||
struct ril_radio;
|
||||
@@ -46,6 +47,7 @@ struct ril_network;
|
||||
struct ril_sim_card;
|
||||
struct ril_sim_info;
|
||||
struct ril_sim_settings;
|
||||
struct ril_cell_info;
|
||||
|
||||
struct ril_slot_config {
|
||||
guint slot;
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Amount of ms we wait between CLCC calls */
|
||||
#include <gutil_ring.h>
|
||||
|
||||
#define FLAG_NEED_CLIP 1
|
||||
#define MAX_DTMF_BUFFER 32
|
||||
|
||||
enum ril_voicecall_events {
|
||||
VOICECALL_EVENT_CALL_STATE_CHANGED,
|
||||
@@ -43,7 +43,7 @@ struct ril_voicecall {
|
||||
ofono_voicecall_cb_t cb;
|
||||
void *data;
|
||||
guint timer_id;
|
||||
gchar *tone_queue;
|
||||
GUtilRing* dtmf_queue;
|
||||
guint send_dtmf_id;
|
||||
guint clcc_poll_id;
|
||||
gulong event_id[VOICECALL_EVENT_COUNT];
|
||||
@@ -52,13 +52,6 @@ struct ril_voicecall {
|
||||
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 ofono_voicecall *vc;
|
||||
ofono_voicecall_cb_t cb;
|
||||
@@ -71,12 +64,6 @@ struct lastcause_req {
|
||||
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_clear_dtmf_queue(struct ril_voicecall *vd);
|
||||
|
||||
@@ -387,9 +374,12 @@ static void ril_voicecall_clcc_poll(struct ril_voicecall *vd)
|
||||
{
|
||||
GASSERT(vd);
|
||||
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,
|
||||
NULL, RIL_REQUEST_GET_CURRENT_CALLS,
|
||||
req, RIL_REQUEST_GET_CURRENT_CALLS,
|
||||
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,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_voicecall_req *cbd = user_data;
|
||||
struct ofono_voicecall *vc = cbd->vc;
|
||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||
struct ril_voicecall *vd = user_data;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
if (vd->cb) {
|
||||
@@ -458,11 +446,21 @@ static void ril_voicecall_dial_cb(GRilIoChannel *io, int status,
|
||||
ril_voicecall_clcc_poll(vd);
|
||||
}
|
||||
} else {
|
||||
struct ofono_error error;
|
||||
ofono_error("call failed.");
|
||||
vd->cb = NULL;
|
||||
vd->data = NULL;
|
||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||
|
||||
/*
|
||||
* Even though this dial request may have already been
|
||||
* completed (successfully) by ril_voicecall_clcc_poll_cb,
|
||||
* RIL_REQUEST_DIAL may still fail.
|
||||
*/
|
||||
if (vd->cb) {
|
||||
struct ofono_error error;
|
||||
ofono_voicecall_cb_t cb = vd->cb;
|
||||
void *cbdata = vd->data;
|
||||
vd->cb = NULL;
|
||||
vd->data = NULL;
|
||||
cb(ril_error_failure(&error), cbdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,27 +470,22 @@ static void ril_voicecall_dial(struct ofono_voicecall *vc,
|
||||
void *data)
|
||||
{
|
||||
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);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
ofono_info("dialing \"%s\"", phstr);
|
||||
|
||||
DBG("%s,%d,0", phstr, clir);
|
||||
cbd->vc = vc;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
|
||||
GASSERT(!vd->cb);
|
||||
vd->cb = cbd->cb;
|
||||
vd->data = cbd->data;
|
||||
vd->cb = cb;
|
||||
vd->data = data;
|
||||
|
||||
grilio_request_append_utf8(req, phstr); /* Number to dial */
|
||||
grilio_request_append_int32(req, clir); /* CLIR mode */
|
||||
grilio_request_append_int32(req, 0); /* UUS information (absent) */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -603,11 +596,6 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
|
||||
vd->send_dtmf_id = 0;
|
||||
|
||||
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 */
|
||||
ril_voicecall_send_one_dtmf(vd);
|
||||
} 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)
|
||||
{
|
||||
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);
|
||||
const char dtmf_char = (char)
|
||||
GPOINTER_TO_UINT(gutil_ring_get(vd->dtmf_queue));
|
||||
|
||||
/* RIL wants just one character */
|
||||
DBG("%c", vd->tone_queue[0]);
|
||||
grilio_request_append_utf8_chars(req, vd->tone_queue, 1);
|
||||
GASSERT(dtmf_char);
|
||||
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,
|
||||
RIL_REQUEST_DTMF, ril_voicecall_send_dtmf_cb, NULL, vd);
|
||||
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 ofono_error error;
|
||||
|
||||
DBG("Queue '%s'",dtmf);
|
||||
|
||||
/*
|
||||
* Queue any incoming DTMF (up to MAX_DTMF_BUFFER characters),
|
||||
* send them to RIL one-by-one, immediately call back
|
||||
* core with no error
|
||||
* Queue any incoming DTMF, send them to RIL one-by-one,
|
||||
* immediately call back core with no error
|
||||
*/
|
||||
g_strlcat(vd->tone_queue, dtmf, MAX_DTMF_BUFFER);
|
||||
ril_voicecall_send_one_dtmf(vd);
|
||||
DBG("Queue '%s'", dtmf);
|
||||
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);
|
||||
}
|
||||
|
||||
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
|
||||
{
|
||||
g_free(vd->tone_queue);
|
||||
vd->tone_queue = g_strnfill(MAX_DTMF_BUFFER + 1, '\0');
|
||||
gutil_ring_clear(vd->dtmf_queue);
|
||||
if (vd->send_dtmf_id) {
|
||||
grilio_channel_cancel_request(vd->io, vd->send_dtmf_id, FALSE);
|
||||
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->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
vd->q = grilio_queue_new(vd->io);
|
||||
vd->dtmf_queue = gutil_ring_new();
|
||||
vd->vc = vc;
|
||||
vd->timer_id = g_idle_add(ril_delayed_register, vd);
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||
|
||||
DBG("");
|
||||
ofono_voicecall_set_data(vc, NULL);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
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]);
|
||||
}
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
|
||||
if (vd->timer_id > 0) {
|
||||
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_unref(vd->ecclist);
|
||||
|
||||
grilio_channel_remove_handlers(vd->io, vd->event_id,
|
||||
G_N_ELEMENTS(vd->event_id));
|
||||
grilio_channel_unref(vd->io);
|
||||
grilio_queue_cancel_all(vd->q, FALSE);
|
||||
grilio_queue_unref(vd->q);
|
||||
g_free(vd->tone_queue);
|
||||
gutil_ring_unref(vd->dtmf_queue);
|
||||
g_free(vd);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Telephony stack for Linux
|
||||
*
|
||||
* 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
|
||||
* 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_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
|
||||
#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
|
||||
#define OFONO_OEM_RAW_INTERFACE "org.ofono.OemRaw"
|
||||
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
|
||||
|
||||
/* CDMA Interfaces */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Telephony stack for Linux
|
||||
*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -22,6 +23,8 @@
|
||||
#ifndef __OFONO_LOG_H
|
||||
#define __OFONO_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -50,6 +53,7 @@ struct ofono_debug_desc {
|
||||
const char *file;
|
||||
#define OFONO_DEBUG_FLAG_DEFAULT (0)
|
||||
#define OFONO_DEBUG_FLAG_PRINT (1 << 0)
|
||||
#define OFONO_DEBUG_FLAG_HIDE_NAME (1 << 1)
|
||||
unsigned int flags;
|
||||
void (*notify)(struct ofono_debug_desc* desc);
|
||||
} __attribute__((aligned(OFONO_DEBUG_ALIGN)));
|
||||
@@ -67,10 +71,20 @@ struct ofono_debug_desc {
|
||||
.file = __FILE__, .flags = OFONO_DEBUG_FLAG_DEFAULT, \
|
||||
}; \
|
||||
if (__ofono_debug_desc.flags & OFONO_DEBUG_FLAG_PRINT) \
|
||||
ofono_debug("%s:%s() " fmt, \
|
||||
__FILE__, __FUNCTION__ , ## arg); \
|
||||
__ofono_dbg(&__ofono_debug_desc, "%s() " fmt, \
|
||||
__FUNCTION__ , ## arg); \
|
||||
} 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
|
||||
}
|
||||
#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,
|
||||
const unsigned char *data,
|
||||
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_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,
|
||||
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,
|
||||
ofono_sim_file_write_cb_t cb,
|
||||
enum ofono_sim_file_structure structure, int record,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
|
||||
#include <gdbus.h>
|
||||
#include <string.h>
|
||||
|
||||
#define OFONO_API_SUBJECT_TO_CHANGE
|
||||
#include <ofono/plugin.h>
|
||||
#include <ofono/dbus.h>
|
||||
#include <ofono/log.h>
|
||||
#include <ofono.h>
|
||||
|
||||
#define DEBUGLOG_INTERFACE OFONO_SERVICE ".DebugLog"
|
||||
#define DEBUGLOG_PATH "/"
|
||||
#define DEBUGLOG_CHANGED_SIGNAL "Changed"
|
||||
#include <dbuslog_server_dbus.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
static DBusConnection *connection = NULL;
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
extern struct ofono_debug_desc __start___debug[];
|
||||
extern struct ofono_debug_desc __stop___debug[];
|
||||
#define DEBUGLOG_PATH "/"
|
||||
|
||||
static void debuglog_signal(DBusConnection *conn, const char *name,
|
||||
guint flags)
|
||||
enum _debug_server_event {
|
||||
DEBUG_EVENT_CATEGORY_ENABLED,
|
||||
DEBUG_EVENT_CATEGORY_DISABLED,
|
||||
DEBUG_EVENT_COUNT
|
||||
};
|
||||
|
||||
static DBusLogServer *debuglog_server;
|
||||
static GLogProc2 debuglog_default_log_proc;
|
||||
static gulong debuglog_event_id[DEBUG_EVENT_COUNT];
|
||||
|
||||
static void debuglog_ofono_log_hook(const struct ofono_debug_desc *desc,
|
||||
int priority, const char *format, va_list va)
|
||||
{
|
||||
DBusMessage *signal = dbus_message_new_signal(DEBUGLOG_PATH,
|
||||
DEBUGLOG_INTERFACE, DEBUGLOG_CHANGED_SIGNAL);
|
||||
DBUSLOG_LEVEL dbuslevel;
|
||||
const char *category;
|
||||
|
||||
if (signal) {
|
||||
DBusMessageIter iter;
|
||||
const dbus_bool_t on = (flags & OFONO_DEBUG_FLAG_PRINT) != 0;
|
||||
|
||||
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);
|
||||
if (desc) {
|
||||
category = desc->name ? desc->name : desc->file;
|
||||
} else {
|
||||
category = NULL;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
@@ -77,197 +176,80 @@ static GHashTable *debuglog_update_flags_hash(GHashTable *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)
|
||||
{
|
||||
DBG("");
|
||||
const struct ofono_debug_desc *start = __start___debug;
|
||||
const struct ofono_debug_desc *stop = __stop___debug;
|
||||
|
||||
connection = ofono_dbus_get_connection();
|
||||
if (!connection)
|
||||
return -1;
|
||||
debuglog_server = dbus_log_server_new(ofono_dbus_get_connection(),
|
||||
DEBUGLOG_PATH);
|
||||
|
||||
if (!g_dbus_register_interface(connection, DEBUGLOG_PATH,
|
||||
DEBUGLOG_INTERFACE, debuglog_methods, debuglog_signals,
|
||||
NULL, NULL, NULL)) {
|
||||
ofono_error("debuglog: failed to register "
|
||||
DEBUGLOG_INTERFACE);
|
||||
return -1;
|
||||
if (start && stop) {
|
||||
const struct ofono_debug_desc *desc;
|
||||
GHashTable *hash = NULL;
|
||||
|
||||
for (desc = start; desc < stop; desc++) {
|
||||
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;
|
||||
}
|
||||
|
||||
static void debuglog_exit(void)
|
||||
{
|
||||
DBG("");
|
||||
|
||||
if (connection) {
|
||||
g_dbus_unregister_interface(connection, DEBUGLOG_PATH,
|
||||
DEBUGLOG_INTERFACE);
|
||||
dbus_connection_unref(connection);
|
||||
connection = NULL;
|
||||
}
|
||||
gutil_log_func2 = debuglog_default_log_proc;
|
||||
dbus_log_server_remove_handlers(debuglog_server, debuglog_event_id,
|
||||
G_N_ELEMENTS(debuglog_event_id));
|
||||
dbus_log_server_unref(debuglog_server);
|
||||
debuglog_server = NULL;
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(debuglog, "Debug log control interface",
|
||||
OFONO_PLUGIN_DEFINE(debuglog, "Debug log interface",
|
||||
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
|
||||
debuglog_init, debuglog_exit)
|
||||
|
||||
@@ -44,6 +44,16 @@
|
||||
|
||||
#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)
|
||||
|
||||
enum MBPI_ERROR {
|
||||
@@ -111,7 +121,7 @@ static void mbpi_g_set_error(GMarkupParseContext *context, GError **error,
|
||||
|
||||
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,
|
||||
@@ -120,7 +130,7 @@ static void text_handler(GMarkupParseContext *context,
|
||||
{
|
||||
char **string = userdata;
|
||||
|
||||
g_free(*string);
|
||||
g_free(*string);
|
||||
*string = g_strndup(text, text_len);
|
||||
}
|
||||
|
||||
@@ -166,7 +176,7 @@ static void authentication_start(GMarkupParseContext *context,
|
||||
static void usage_start(GMarkupParseContext *context,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
enum ofono_gprs_context_type *type, GError **error)
|
||||
struct ofono_gprs_provision_data *apn, GError **error)
|
||||
{
|
||||
const char *text = NULL;
|
||||
int i;
|
||||
@@ -182,12 +192,14 @@ static void usage_start(GMarkupParseContext *context,
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(text, "internet") == 0)
|
||||
*type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||
else if (strcmp(text, "mms") == 0)
|
||||
*type = OFONO_GPRS_CONTEXT_TYPE_MMS;
|
||||
else if (strcmp(text, "wap") == 0)
|
||||
*type = OFONO_GPRS_CONTEXT_TYPE_WAP;
|
||||
if (strcmp(text, "internet") == 0) {
|
||||
apn->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||
apn->proto = mbpi_default_internet_proto;
|
||||
} else if (strcmp(text, "mms") == 0) {
|
||||
apn->type = OFONO_GPRS_CONTEXT_TYPE_MMS;
|
||||
apn->proto = mbpi_default_mms_proto;
|
||||
} else if (strcmp(text, "wap") == 0)
|
||||
apn->type = OFONO_GPRS_CONTEXT_TYPE_WAP;
|
||||
else
|
||||
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
||||
@@ -220,7 +232,7 @@ static void apn_start(GMarkupParseContext *context, const gchar *element_name,
|
||||
&apn->message_proxy);
|
||||
else if (g_str_equal(element_name, "usage"))
|
||||
usage_start(context, attribute_names, attribute_values,
|
||||
&apn->type, error);
|
||||
apn, error);
|
||||
}
|
||||
|
||||
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->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;
|
||||
|
||||
g_markup_parse_context_push(context, &apn_parser, ap);
|
||||
@@ -611,11 +623,11 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
||||
GMarkupParseContext *context;
|
||||
gboolean ret;
|
||||
|
||||
fd = open(MBPI_DATABASE, O_RDONLY);
|
||||
fd = open(mbpi_database, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
g_set_error(error, G_FILE_ERROR,
|
||||
g_file_error_from_errno(errno),
|
||||
"open(%s) failed: %s", MBPI_DATABASE,
|
||||
"open(%s) failed: %s", mbpi_database,
|
||||
g_strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
@@ -624,7 +636,7 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
||||
close(fd);
|
||||
g_set_error(error, G_FILE_ERROR,
|
||||
g_file_error_from_errno(errno),
|
||||
"fstat(%s) failed: %s", MBPI_DATABASE,
|
||||
"fstat(%s) failed: %s", mbpi_database,
|
||||
g_strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
@@ -634,7 +646,7 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
||||
close(fd);
|
||||
g_set_error(error, G_FILE_ERROR,
|
||||
g_file_error_from_errno(errno),
|
||||
"mmap(%s) failed: %s", MBPI_DATABASE,
|
||||
"mmap(%s) failed: %s", mbpi_database,
|
||||
g_strerror(errno));
|
||||
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);
|
||||
|
||||
void mbpi_ap_free(struct ofono_gprs_provision_data *data);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* 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
|
||||
* 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 */
|
||||
static GSList *provision_pick_best_ap(GSList *list, const char* spn,
|
||||
const enum ofono_gprs_proto default_proto,
|
||||
const struct provision_ap_defaults *defaults)
|
||||
{
|
||||
/* Sort the list */
|
||||
@@ -101,6 +102,7 @@ static GSList *provision_pick_best_ap(GSList *list, const char* spn,
|
||||
struct ofono_gprs_provision_data *ap =
|
||||
g_new0(struct ofono_gprs_provision_data, 1);
|
||||
|
||||
ap->proto = default_proto;
|
||||
ap->type = defaults->type;
|
||||
ap->name = g_strdup(defaults->name);
|
||||
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 */
|
||||
return g_slist_concat(
|
||||
provision_pick_best_ap(internet_apns, spn, &internet_defaults),
|
||||
provision_pick_best_ap(mms_apns, spn, &mms_defaults));
|
||||
provision_pick_best_ap(internet_apns, spn,
|
||||
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,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -37,6 +38,9 @@
|
||||
|
||||
#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_path;
|
||||
|
||||
@@ -56,6 +60,12 @@ void ofono_info(const char *format, ...)
|
||||
vsyslog(LOG_INFO, format, 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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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__
|
||||
@@ -306,6 +359,7 @@ int __ofono_log_init(const char *program, const char *debug,
|
||||
|
||||
program_exec = program;
|
||||
program_path = getcwd(path, sizeof(path));
|
||||
ofono_debug_str = g_string_sized_new(127);
|
||||
|
||||
if (debug != NULL)
|
||||
enabled = g_strsplit_set(debug, ":, ", 0);
|
||||
@@ -339,4 +393,6 @@ void __ofono_log_cleanup(ofono_bool_t backtrace)
|
||||
#endif
|
||||
|
||||
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,
|
||||
(GCompareFunc) strcmp);
|
||||
if (found == NULL) {
|
||||
ofono_error("Interface %s not found on the interface_list",
|
||||
DBG("Interface %s not found on the interface_list",
|
||||
interface);
|
||||
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_NETREG,
|
||||
OFONO_ATOM_TYPE_HANDSFREE,
|
||||
OFONO_ATOM_TYPE_OEM_RAW,
|
||||
OFONO_ATOM_TYPE_SIRI,
|
||||
};
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ enum phonebook_number_type {
|
||||
};
|
||||
|
||||
struct ofono_phonebook {
|
||||
DBusMessage *pending;
|
||||
GSList *pending;
|
||||
int storage_index; /* go through all supported storage */
|
||||
int flags;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DBusMessage *reply;
|
||||
const char *pb = storage_support[phonebook->storage_index];
|
||||
|
||||
if (pb) {
|
||||
@@ -442,13 +457,9 @@ static void export_phonebook(struct ofono_phonebook *phonebook)
|
||||
return;
|
||||
}
|
||||
|
||||
reply = generate_export_entries_reply(phonebook, phonebook->pending);
|
||||
if (reply == NULL) {
|
||||
dbus_message_unref(phonebook->pending);
|
||||
return;
|
||||
}
|
||||
|
||||
__ofono_dbus_pending_reply(&phonebook->pending, reply);
|
||||
g_slist_foreach(phonebook->pending, phonebook_reply, phonebook);
|
||||
g_slist_free(phonebook->pending);
|
||||
phonebook->pending = NULL;
|
||||
phonebook->flags |= PHONEBOOK_FLAG_CACHED;
|
||||
}
|
||||
|
||||
@@ -458,23 +469,22 @@ static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg,
|
||||
struct ofono_phonebook *phonebook = data;
|
||||
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) {
|
||||
reply = generate_export_entries_reply(phonebook, msg);
|
||||
g_dbus_send_message(conn, reply);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_string_set_size(phonebook->vcards, 0);
|
||||
phonebook->storage_index = 0;
|
||||
|
||||
phonebook->pending = dbus_message_ref(msg);
|
||||
export_phonebook(phonebook);
|
||||
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);
|
||||
phonebook->storage_index = 0;
|
||||
export_phonebook(phonebook);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -516,6 +526,11 @@ static void phonebook_unregister(struct ofono_atom *atom)
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
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);
|
||||
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,
|
||||
SIM_SST_SERVICE_BDN)) {
|
||||
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);
|
||||
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,
|
||||
SIM_SST_SERVICE_FDN)) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
ofono_sim_file_write_cb_t cb,
|
||||
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)
|
||||
((sim_fs_read_info_cb_t) op->cb)
|
||||
((ofono_sim_read_info_cb_t) op->cb)
|
||||
(0, 0, 0, 0, op->userdata);
|
||||
else if (op->is_read == TRUE)
|
||||
((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);
|
||||
}
|
||||
|
||||
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,
|
||||
const unsigned char *data, int len,
|
||||
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,
|
||||
op->record_length,
|
||||
NULL, 0,
|
||||
op->path_len ? op->path : NULL,
|
||||
op->path_len,
|
||||
sim_fs_op_retrieve_cb, fs);
|
||||
break;
|
||||
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,
|
||||
op->record_length,
|
||||
NULL, 0,
|
||||
op->path_len ? op->path : NULL,
|
||||
op->path_len,
|
||||
sim_fs_op_retrieve_cb, fs);
|
||||
break;
|
||||
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
|
||||
* 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,
|
||||
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
|
||||
* 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,
|
||||
op->record_length, op->userdata);
|
||||
@@ -820,7 +843,28 @@ static gboolean sim_fs_op_next(gpointer user_data)
|
||||
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))
|
||||
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,
|
||||
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_op *op;
|
||||
@@ -887,6 +932,8 @@ int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
||||
op->is_read = TRUE;
|
||||
op->info_only = TRUE;
|
||||
op->context = context;
|
||||
memcpy(op->path, path, pth_len);
|
||||
op->path_len = pth_len;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
ofono_sim_file_write_cb_t cb,
|
||||
enum ofono_sim_file_structure structure, int record,
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
|
||||
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,
|
||||
const struct ofono_sim_driver *driver);
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ Source: %{name}-%{version}.tar.bz2
|
||||
Requires: dbus
|
||||
Requires: systemd
|
||||
Requires: ofono-configs
|
||||
Requires: libgrilio >= 1.0.6
|
||||
Requires: libglibutil >= 1.0.6
|
||||
Requires: libgrilio >= 1.0.10
|
||||
Requires: libglibutil >= 1.0.10
|
||||
Requires(preun): systemd
|
||||
Requires(post): systemd
|
||||
Requires(postun): systemd
|
||||
@@ -21,8 +21,9 @@ BuildRequires: pkgconfig(libudev) >= 145
|
||||
BuildRequires: pkgconfig(bluez) >= 4.85
|
||||
BuildRequires: pkgconfig(mobile-broadband-provider-info)
|
||||
BuildRequires: pkgconfig(libwspcodec) >= 2.0
|
||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.6
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.6
|
||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.10
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.10
|
||||
BuildRequires: pkgconfig(libdbuslogserver-dbus)
|
||||
BuildRequires: libtool
|
||||
BuildRequires: automake
|
||||
BuildRequires: autoconf
|
||||
@@ -69,7 +70,7 @@ autoreconf --force --install
|
||||
|
||||
%configure --disable-static \
|
||||
--enable-test \
|
||||
--enable-logcontrol \
|
||||
--enable-debuglog \
|
||||
--enable-jolla-rilmodem \
|
||||
--with-systemdunitdir="/%{_lib}/systemd/system"
|
||||
|
||||
@@ -86,6 +87,7 @@ rm -rf %{buildroot}
|
||||
|
||||
mkdir -p %{buildroot}/%{_sysconfdir}/ofono/push_forwarder.d
|
||||
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
|
||||
|
||||
%preun
|
||||
|
||||
Reference in New Issue
Block a user