Compare commits

..

3 Commits

Author SHA1 Message Date
Slava Monich
9bede136cc [ril] Handle NITZ string without DST part. Fixes JB#41890 2018-05-16 16:16:31 +03:00
Slava Monich
b3380c6eca [ril] Don't wait for SIM state change after enabling/disabling pin. JB#41508
There's no real need for that, but most importantly no SIM state change
event is generated by MTK RIL in such cases.
2018-05-14 18:51:31 +03:00
Slava Monich
f98e9a2193 ussd: Don't ignore data from TERMINATED response
Typically responses to USSD requests are coming with status
zero (NOTIFY) but some are coming with status 2 (TERMINATED).
If those contain data, the data should be presented to the user.

[ussd] Don't ignore data from TERMINATED response. Fixes JB#41734
2018-04-25 11:07:35 +03:00
60 changed files with 1081 additions and 5150 deletions

4
ofono/.gitignore vendored
View File

@@ -32,8 +32,6 @@ src/ofono.service
dundee/dundee dundee/dundee
dundee/dundee.service dundee/dundee.service
test-driver
test-suite.log
unit/test-common unit/test-common
unit/test-util unit/test-util
unit/test-idmap unit/test-idmap
@@ -48,7 +46,6 @@ unit/test-dbus-queue
unit/test-gprs-filter unit/test-gprs-filter
unit/test-ril_config unit/test-ril_config
unit/test-ril_util unit/test-ril_util
unit/test-ril-transport
unit/test-rilmodem-cb unit/test-rilmodem-cb
unit/test-rilmodem-cs unit/test-rilmodem-cs
unit/test-rilmodem-gprs unit/test-rilmodem-gprs
@@ -60,7 +57,6 @@ unit/test-sailfish_sim_info
unit/test-sailfish_sim_info_dbus unit/test-sailfish_sim_info_dbus
unit/test-sailfish_watch unit/test-sailfish_watch
unit/test-sms-filter unit/test-sms-filter
unit/test-voicecall-filter
unit/test-*.log unit/test-*.log
unit/test-*.trs unit/test-*.trs

View File

@@ -24,8 +24,6 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/sim-mnclength.h \ include/sim-mnclength.h \
include/handsfree-audio.h include/siri.h \ include/handsfree-audio.h include/siri.h \
include/sms-filter.h include/gprs-filter.h \ include/sms-filter.h include/gprs-filter.h \
include/voicecall-filter.h \
include/ril-constants.h include/ril-transport.h \
include/netmon.h include/lte.h \ include/netmon.h include/lte.h \
include/storage.h \ include/storage.h \
gdbus/gdbus.h gdbus/gdbus.h
@@ -739,7 +737,6 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
src/handsfree-audio.c src/bluetooth.h \ src/handsfree-audio.c src/bluetooth.h \
src/sim-mnclength.c src/voicecallagent.c \ src/sim-mnclength.c src/voicecallagent.c \
src/sms-filter.c src/gprs-filter.c src/dbus-queue.c \ src/sms-filter.c src/gprs-filter.c src/dbus-queue.c \
src/voicecall-filter.c src/ril-transport.c \
src/hfp.h src/siri.c \ src/hfp.h src/siri.c \
src/netmon.c src/lte.c \ src/netmon.c src/lte.c \
src/netmonagent.c src/netmonagent.h src/netmonagent.c src/netmonagent.h
@@ -752,8 +749,7 @@ src_ofonod_LDFLAGS = -Wl,--export-dynamic \
BUILT_SOURCES = $(local_headers) src/builtin.h BUILT_SOURCES = $(local_headers) src/builtin.h
CLEANFILES = $(BUILT_SOURCES) $(rules_DATA) \ CLEANFILES = $(BUILT_SOURCES) $(rules_DATA)
$(shell find . -name "*.gcda") $(shell find . -name "*.gcno")
plugindir = $(pkglibdir)/plugins plugindir = $(pkglibdir)/plugins
@@ -1097,13 +1093,6 @@ unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_provision_OBJECTS) unit_objects += $(unit_test_provision_OBJECTS)
unit_tests += unit/test-provision unit_tests += unit/test-provision
unit_test_ril_transport_SOURCES = unit/test-ril-transport.c \
src/ril-transport.c src/log.c
unit_test_ril_transport_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_ril_transport_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_ril_transport_OBJECTS)
unit_tests += unit/test-ril-transport
unit_test_sms_filter_SOURCES = unit/test-sms-filter.c \ unit_test_sms_filter_SOURCES = unit/test-sms-filter.c \
src/sms-filter.c src/log.c src/sms-filter.c src/log.c
unit_test_sms_filter_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) unit_test_sms_filter_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
@@ -1118,14 +1107,6 @@ unit_test_gprs_filter_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_gprs_filter_OBJECTS) unit_objects += $(unit_test_gprs_filter_OBJECTS)
unit_tests += unit/test-gprs-filter unit_tests += unit/test-gprs-filter
unit_test_voicecall_filter_SOURCES = unit/test-voicecall-filter.c \
src/voicecall-filter.c src/log.c \
src/common.c src/util.c
unit_test_voicecall_filter_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_voicecall_filter_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_voicecall_filter_OBJECTS)
unit_tests += unit/test-voicecall-filter
test_rilmodem_sources = $(gril_sources) src/log.c src/common.c src/util.c \ test_rilmodem_sources = $(gril_sources) src/log.c src/common.c src/util.c \
gatchat/ringbuffer.h gatchat/ringbuffer.c \ gatchat/ringbuffer.h gatchat/ringbuffer.c \
unit/rilmodem-test-server.h \ unit/rilmodem-test-server.h \

View File

@@ -184,10 +184,10 @@ AC_ARG_ENABLE(sailfish-rilmodem, AC_HELP_STRING([--enable-sailfish-rilmodem],
AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no") AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no")
if (test "${enable_sailfish_rilmodem}" = "yes"); then if (test "${enable_sailfish_rilmodem}" = "yes"); then
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.25, dummy=yes, PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.21, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.25 is required)) AC_MSG_ERROR(libgrilio >= 1.0.21 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.30, dummy=yes, PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.23, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.30 is required)) AC_MSG_ERROR(libglibutil >= 1.0.23 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.5, dummy=yes, PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.5, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.5 is required)) AC_MSG_ERROR(libmce-glib >= 1.0.5 is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $LIBMCE_CFLAGS" CFLAGS="$CFLAGS $GRILIO_CFLAGS $LIBMCE_CFLAGS"

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2018 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -14,7 +14,6 @@
*/ */
#include "ril_plugin.h" #include "ril_plugin.h"
#include "ril_sim_card.h"
#include "ril_util.h" #include "ril_util.h"
#include "ril_log.h" #include "ril_log.h"
@@ -27,11 +26,11 @@
* ril.h does not state that string count must be given, but that is * ril.h does not state that string count must be given, but that is
* still expected by the modem * still expected by the modem
*/ */
#define RIL_QUERY_STRING_COUNT 4
#define RIL_SET_STRING_COUNT 5 #define RIL_SET_STRING_COUNT 5
#define RIL_SET_PW_STRING_COUNT 3 #define RIL_SET_PW_STRING_COUNT 3
struct ril_call_barring { struct ril_call_barring {
struct ril_sim_card *card;
GRilIoQueue *q; GRilIoQueue *q;
guint timer_id; guint timer_id;
}; };
@@ -107,7 +106,7 @@ static void ril_call_barring_query(struct ofono_call_barring *b,
{ {
struct ril_call_barring *bd = ofono_call_barring_get_data(b); struct ril_call_barring *bd = ofono_call_barring_get_data(b);
char cls_textual[RIL_MAX_SERVICE_LENGTH]; char cls_textual[RIL_MAX_SERVICE_LENGTH];
GRilIoRequest *req; GRilIoRequest *req = grilio_request_new();
DBG("lock: %s, services to query: %d", lock, cls); DBG("lock: %s, services to query: %d", lock, cls);
@@ -124,9 +123,15 @@ static void ril_call_barring_query(struct ofono_call_barring *b,
/* /*
* See 3GPP 27.007 7.4 for parameter descriptions. * See 3GPP 27.007 7.4 for parameter descriptions.
* According to ril.h password should be empty string "" when not
* needed, but in reality we only need to give string length as 0
*/ */
req = grilio_request_array_utf8_new(4, lock, "", cls_textual, grilio_request_append_int32(req, RIL_QUERY_STRING_COUNT);
ril_sim_card_app_aid(bd->card)); grilio_request_append_utf8(req, lock); /* Facility code */
grilio_request_append_int32(req, 0); /* Password length */
grilio_request_append_utf8(req, cls_textual);
grilio_request_append_utf8(req, NULL); /* AID (not yet supported) */
ril_call_barring_submit_request(bd, req, ril_call_barring_submit_request(bd, req,
RIL_REQUEST_QUERY_FACILITY_LOCK, RIL_REQUEST_QUERY_FACILITY_LOCK,
ril_call_barring_query_cb, cb, data); ril_call_barring_query_cb, cb, data);
@@ -177,7 +182,7 @@ static void ril_call_barring_set(struct ofono_call_barring *b,
RIL_FACILITY_UNLOCK); RIL_FACILITY_UNLOCK);
grilio_request_append_utf8(req, passwd); grilio_request_append_utf8(req, passwd);
grilio_request_append_utf8(req, cls_textual); grilio_request_append_utf8(req, cls_textual);
grilio_request_append_utf8(req, ril_sim_card_app_aid(bd->card)); grilio_request_append_utf8(req, NULL); /* AID (not yet supported) */
ril_call_barring_submit_request(bd, req, ril_call_barring_submit_request(bd, req,
RIL_REQUEST_SET_FACILITY_LOCK, RIL_REQUEST_SET_FACILITY_LOCK,
@@ -238,7 +243,6 @@ static int ril_call_barring_probe(struct ofono_call_barring *b,
struct ril_call_barring *bd = g_new0(struct ril_call_barring, 1); struct ril_call_barring *bd = g_new0(struct ril_call_barring, 1);
DBG(""); DBG("");
bd->card = ril_sim_card_ref(modem->sim_card);
bd->q = grilio_queue_new(ril_modem_io(modem)); bd->q = grilio_queue_new(ril_modem_io(modem));
bd->timer_id = g_idle_add(ril_call_barring_register, b); bd->timer_id = g_idle_add(ril_call_barring_register, b);
ofono_call_barring_set_data(b, bd); ofono_call_barring_set_data(b, bd);
@@ -256,7 +260,6 @@ static void ril_call_barring_remove(struct ofono_call_barring *b)
g_source_remove(bd->timer_id); g_source_remove(bd->timer_id);
} }
ril_sim_card_unref(bd->card);
grilio_queue_cancel_all(bd->q, FALSE); grilio_queue_cancel_all(bd->q, FALSE);
grilio_queue_unref(bd->q); grilio_queue_unref(bd->q);
g_free(bd); g_free(bd);

View File

@@ -23,7 +23,6 @@
#include <grilio_request.h> #include <grilio_request.h>
#include <grilio_parser.h> #include <grilio_parser.h>
#include <gutil_idlepool.h>
#include <gutil_misc.h> #include <gutil_misc.h>
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */ #define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
@@ -76,20 +75,6 @@ static void ril_cell_free1(gpointer cell)
ril_cell_free(cell); ril_cell_free(cell);
} }
static const char *ril_cell_info_int_format(int value, const char *format)
{
if (value == SAILFISH_CELL_INVALID_VALUE) {
return "";
} else {
static GUtilIdlePool *ril_cell_info_pool = NULL;
GUtilIdlePool *pool = gutil_idle_pool_get(&ril_cell_info_pool);
char *str = g_strdup_printf(format, value);
gutil_idle_pool_add(pool, str, g_free);
return str;
}
}
static gboolean ril_cell_info_list_identical(GSList *l1, GSList *l2) static gboolean ril_cell_info_list_identical(GSList *l1, GSList *l2)
{ {
while (l1 && l2) { while (l1 && l2) {
@@ -138,17 +123,11 @@ static struct sailfish_cell *ril_cell_info_parse_cell_gsm(GRilIoParser *rilp,
grilio_parser_get_int32(rilp, &gsm->bitErrorRate) && grilio_parser_get_int32(rilp, &gsm->bitErrorRate) &&
(version < 12 || /* RIL_GSM_SignalStrength_v12 part */ (version < 12 || /* RIL_GSM_SignalStrength_v12 part */
grilio_parser_get_int32(rilp, &gsm->timingAdvance))) { grilio_parser_get_int32(rilp, &gsm->timingAdvance))) {
DBG("[gsm] reg=%d%s%s%s%s%s%s%s%s%s", registered, DBG("[gsm] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,arfcn=%d,"
ril_cell_info_int_format(gsm->mcc, ",mcc=%d"), "bsic=%d,strength=%d,err=%d,t=%d", registered,
ril_cell_info_int_format(gsm->mnc, ",mnc=%d"), gsm->mcc, gsm->mnc, gsm->lac, gsm->cid, gsm->arfcn,
ril_cell_info_int_format(gsm->lac, ",lac=%d"), gsm->bsic, gsm->signalStrength, gsm->bitErrorRate,
ril_cell_info_int_format(gsm->cid, ",cid=%d"), gsm->timingAdvance);
ril_cell_info_int_format(gsm->arfcn, ",arfcn=%d"),
ril_cell_info_int_format(gsm->bsic, ",bsic=%d"),
ril_cell_info_int_format(gsm->signalStrength,
",strength=%d"),
ril_cell_info_int_format(gsm->bitErrorRate, ",err=%d"),
ril_cell_info_int_format(gsm->timingAdvance, ",t=%d"));
cell->type = SAILFISH_CELL_TYPE_GSM; cell->type = SAILFISH_CELL_TYPE_GSM;
cell->registered = registered; cell->registered = registered;
return cell; return cell;
@@ -176,16 +155,10 @@ static struct sailfish_cell *ril_cell_info_parse_cell_wcdma(GRilIoParser *rilp,
grilio_parser_get_int32(rilp, &wcdma->uarfcn)) && grilio_parser_get_int32(rilp, &wcdma->uarfcn)) &&
grilio_parser_get_int32(rilp, &wcdma->signalStrength) && grilio_parser_get_int32(rilp, &wcdma->signalStrength) &&
grilio_parser_get_int32(rilp, &wcdma->bitErrorRate)) { grilio_parser_get_int32(rilp, &wcdma->bitErrorRate)) {
DBG("[wcdma] reg=%d%s%s%s%s%s%s%s", registered, DBG("[wcdma] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,psc=%d,"
ril_cell_info_int_format(wcdma->mcc, ",mcc=%d"), "strength=%d,err=%d", registered, wcdma->mcc,
ril_cell_info_int_format(wcdma->mnc, ",mnc=%d"), wcdma->mnc, wcdma->lac, wcdma->cid, wcdma->psc,
ril_cell_info_int_format(wcdma->lac, ",lac=%d"), wcdma->signalStrength, wcdma->bitErrorRate);
ril_cell_info_int_format(wcdma->cid, ",cid=%d"),
ril_cell_info_int_format(wcdma->psc, ",psc=%d"),
ril_cell_info_int_format(wcdma->signalStrength,
",strength=%d"),
ril_cell_info_int_format(wcdma->bitErrorRate,
",err=%d"));
cell->type = SAILFISH_CELL_TYPE_WCDMA; cell->type = SAILFISH_CELL_TYPE_WCDMA;
cell->registered = registered; cell->registered = registered;
return cell; return cell;
@@ -217,19 +190,11 @@ static struct sailfish_cell *ril_cell_info_parse_cell_lte(GRilIoParser *rilp,
grilio_parser_get_int32(rilp, &lte->rssnr) && grilio_parser_get_int32(rilp, &lte->rssnr) &&
grilio_parser_get_int32(rilp, &lte->cqi) && grilio_parser_get_int32(rilp, &lte->cqi) &&
grilio_parser_get_int32(rilp, &lte->timingAdvance)) { grilio_parser_get_int32(rilp, &lte->timingAdvance)) {
DBG("[lte] reg=%d%s%s%s%s%s%s%s%s%s%s%s", registered, DBG("[lte] reg=%d,mcc=%d,mnc=%d,ci=%d,pci=%d,tac=%d,"
ril_cell_info_int_format(lte->mcc, ",mcc=%d"), "strength=%d,rsrp=%d,rsrq=%d,rssnr=%d,cqi=%d,"
ril_cell_info_int_format(lte->mnc, ",mnc=%d"), "t=0x%x", registered, lte->mcc, lte->mnc, lte->ci,
ril_cell_info_int_format(lte->ci, ",ci=%d"), lte->pci, lte->tac, lte->signalStrength, lte->rsrp,
ril_cell_info_int_format(lte->pci, ",pci=%d"), lte->rsrq, lte->rssnr, lte->cqi, lte->timingAdvance);
ril_cell_info_int_format(lte->tac, ",tac=%d"),
ril_cell_info_int_format(lte->signalStrength,
",strength=%d"),
ril_cell_info_int_format(lte->rsrp, ",rsrp=%d"),
ril_cell_info_int_format(lte->rsrq, ",rsrq=%d"),
ril_cell_info_int_format(lte->rssnr, ",rssnr=%d"),
ril_cell_info_int_format(lte->cqi, ",cqi=%d"),
ril_cell_info_int_format(lte->timingAdvance, ",t=%d"));
cell->type = SAILFISH_CELL_TYPE_LTE; cell->type = SAILFISH_CELL_TYPE_LTE;
cell->registered = registered; cell->registered = registered;
return cell; return cell;

View File

@@ -19,7 +19,6 @@
#include <gutil_intarray.h> #include <gutil_intarray.h>
#include <gutil_ints.h> #include <gutil_ints.h>
#include <gutil_misc.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -207,7 +206,7 @@ GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
while (*ptr) { while (*ptr) {
int val; int val;
if (gutil_parse_int(*ptr++, 0, &val)) { if (ril_parse_int(*ptr++, 0, &val)) {
gutil_int_array_append(array, val); gutil_int_array_append(array, val);
} }
} }

View File

@@ -1,6 +1,10 @@
/* /*
* RIL constants adopted from AOSP's header:
*
* /hardware/ril/reference_ril/ril.h
*
* Copyright (C) 2013 Canonical Ltd. * Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2018 Jolla Ltd. * Copyright (C) 2013-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -15,10 +19,81 @@
#ifndef __RIL_CONSTANTS_H #ifndef __RIL_CONSTANTS_H
#define __RIL_CONSTANTS_H 1 #define __RIL_CONSTANTS_H 1
#include <ofono/ril-constants.h>
#define RIL_MAX_UUID_LENGTH 64 #define RIL_MAX_UUID_LENGTH 64
/* Error Codes */
enum ril_status {
RIL_E_SUCCESS = 0,
RIL_E_RADIO_NOT_AVAILABLE = 1,
RIL_E_GENERIC_FAILURE = 2,
RIL_E_PASSWORD_INCORRECT = 3,
RIL_E_SIM_PIN2 = 4,
RIL_E_SIM_PUK2 = 5,
RIL_E_REQUEST_NOT_SUPPORTED = 6,
RIL_E_CANCELLED = 7,
RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL = 8,
RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9,
RIL_E_SMS_SEND_FAIL_RETRY = 10,
RIL_E_SIM_ABSENT = 11,
RIL_E_SUBSCRIPTION_NOT_AVAILABLE = 12,
RIL_E_MODE_NOT_SUPPORTED = 13,
RIL_E_FDN_CHECK_FAILURE = 14,
RIL_E_ILLEGAL_SIM_OR_ME = 15,
RIL_E_MISSING_RESOURCE = 16,
RIL_E_NO_SUCH_ELEMENT = 17,
RIL_E_DIAL_MODIFIED_TO_USSD = 18,
RIL_E_DIAL_MODIFIED_TO_SS = 19,
RIL_E_DIAL_MODIFIED_TO_DIAL = 20,
RIL_E_USSD_MODIFIED_TO_DIAL = 21,
RIL_E_USSD_MODIFIED_TO_SS = 22,
RIL_E_USSD_MODIFIED_TO_USSD = 23,
RIL_E_SS_MODIFIED_TO_DIAL = 24,
RIL_E_SS_MODIFIED_TO_USSD = 25,
RIL_E_SUBSCRIPTION_NOT_SUPPORTED = 26,
RIL_E_SS_MODIFIED_TO_SS = 27,
RIL_E_LCE_NOT_SUPPORTED = 36,
RIL_E_NO_MEMORY = 37,
RIL_E_INTERNAL_ERR = 38,
RIL_E_SYSTEM_ERR = 39,
RIL_E_MODEM_ERR = 40,
RIL_E_INVALID_STATE = 41,
RIL_E_NO_RESOURCES = 42,
RIL_E_SIM_ERR = 43,
RIL_E_INVALID_ARGUMENTS = 44,
RIL_E_INVALID_SIM_STATE = 45,
RIL_E_INVALID_MODEM_STATE = 46,
RIL_E_INVALID_CALL_ID = 47,
RIL_E_NO_SMS_TO_ACK = 48,
RIL_E_NETWORK_ERR = 49,
RIL_E_REQUEST_RATE_LIMITED = 50,
RIL_E_SIM_BUSY = 51,
RIL_E_SIM_FULL = 52,
RIL_E_NETWORK_REJECT = 53,
RIL_E_OPERATION_NOT_ALLOWED = 54,
RIL_E_EMPTY_RECORD = 55,
RIL_E_INVALID_SMS_FORMAT = 56,
RIL_E_ENCODING_ERR = 57,
RIL_E_INVALID_SMSC_ADDRESS = 58,
RIL_E_NO_SUCH_ENTRY = 59,
RIL_E_NETWORK_NOT_READY = 60,
RIL_E_NOT_PROVISIONED = 61,
RIL_E_NO_SUBSCRIPTION = 62,
RIL_E_NO_NETWORK_FOUND = 63,
RIL_E_DEVICE_IN_USE = 64,
RIL_E_ABORTED = 65,
RIL_E_INVALID_RESPONSE = 66
};
/* call states */
enum ril_call_state {
RIL_CALL_ACTIVE = 0,
RIL_CALL_HOLDING = 1,
RIL_CALL_DIALING = 2,
RIL_CALL_ALERTING = 3,
RIL_CALL_INCOMING = 4,
RIL_CALL_WAITING = 5
};
/* Radio state */ /* Radio state */
enum ril_radio_state { enum ril_radio_state {
RADIO_STATE_OFF = 0, RADIO_STATE_OFF = 0,
@@ -192,30 +267,30 @@ enum ril_call_fail_cause {
}; };
enum ril_data_call_fail_cause { enum ril_data_call_fail_cause {
PDP_FAIL_NONE = 0, PDP_FAIL_NONE = 0,
PDP_FAIL_OPERATOR_BARRED = 0x08, PDP_FAIL_OPERATOR_BARRED = 0x08,
PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A, PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A,
PDP_FAIL_MISSING_UKNOWN_APN = 0x1B, PDP_FAIL_MISSING_UKNOWN_APN = 0x1B,
PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C, PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C,
PDP_FAIL_USER_AUTHENTICATION = 0x1D, PDP_FAIL_USER_AUTHENTICATION = 0x1D,
PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E, PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E,
PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F, PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F,
PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20, PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20,
PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21, PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21,
PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22, PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22,
PDP_FAIL_NSAPI_IN_USE = 0x23, PDP_FAIL_NSAPI_IN_USE = 0x23,
PDP_FAIL_REGULAR_DEACTIVATION = 0x24, PDP_FAIL_REGULAR_DEACTIVATION = 0x24,
PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32, PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32,
PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33, PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33,
PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34, PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34,
PDP_FAIL_PROTOCOL_ERRORS = 0x6F, PDP_FAIL_PROTOCOL_ERRORS = 0x6F,
PDP_FAIL_VOICE_REGISTRATION_FAIL = -1, PDP_FAIL_VOICE_REGISTRATION_FAIL = -1,
PDP_FAIL_DATA_REGISTRATION_FAIL = -2, PDP_FAIL_DATA_REGISTRATION_FAIL = -2,
PDP_FAIL_SIGNAL_LOST = -3, PDP_FAIL_SIGNAL_LOST = -3,
PDP_FAIL_PREF_RADIO_TECH_CHANGED = -4, PDP_FAIL_PREF_RADIO_TECH_CHANGED = -4,
PDP_FAIL_RADIO_POWER_OFF = -5, PDP_FAIL_RADIO_POWER_OFF = -5,
PDP_FAIL_TETHERED_CALL_ACTIVE = -6, PDP_FAIL_TETHERED_CALL_ACTIVE = -6,
PDP_FAIL_ERROR_UNSPECIFIED = 0xffff PDP_FAIL_ERROR_UNSPECIFIED = 0xffff
}; };
/* RIL_REQUEST_DEACTIVATE_DATA_CALL parameter */ /* RIL_REQUEST_DEACTIVATE_DATA_CALL parameter */
@@ -320,13 +395,191 @@ enum ril_cell_info_type {
RIL_CELL_INFO_TYPE_TD_SCDMA = 5 RIL_CELL_INFO_TYPE_TD_SCDMA = 5
}; };
enum ril_restricted_state { /* RIL Request Messages, ofono -> rild */
RIL_RESTRICTED_STATE_NONE = 0x00, #define RIL_REQUEST_GET_SIM_STATUS 1
RIL_RESTRICTED_STATE_CS_EMERGENCY = 0x01, #define RIL_REQUEST_ENTER_SIM_PIN 2
RIL_RESTRICTED_STATE_CS_NORMAL = 0x02, #define RIL_REQUEST_ENTER_SIM_PUK 3
RIL_RESTRICTED_STATE_CS_ALL = 0x04, #define RIL_REQUEST_ENTER_SIM_PIN2 4
RIL_RESTRICTED_STATE_PS_ALL = 0x10 #define RIL_REQUEST_ENTER_SIM_PUK2 5
}; #define RIL_REQUEST_CHANGE_SIM_PIN 6
#define RIL_REQUEST_CHANGE_SIM_PIN2 7
#define RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION 8
#define RIL_REQUEST_GET_CURRENT_CALLS 9
#define RIL_REQUEST_DIAL 10
#define RIL_REQUEST_GET_IMSI 11
#define RIL_REQUEST_HANGUP 12
#define RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND 13
#define RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND 14
#define RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE 15
#define RIL_REQUEST_CONFERENCE 16
#define RIL_REQUEST_UDUB 17
#define RIL_REQUEST_LAST_CALL_FAIL_CAUSE 18
#define RIL_REQUEST_SIGNAL_STRENGTH 19
#define RIL_REQUEST_VOICE_REGISTRATION_STATE 20
#define RIL_REQUEST_DATA_REGISTRATION_STATE 21
#define RIL_REQUEST_OPERATOR 22
#define RIL_REQUEST_RADIO_POWER 23
#define RIL_REQUEST_DTMF 24
#define RIL_REQUEST_SEND_SMS 25
#define RIL_REQUEST_SEND_SMS_EXPECT_MORE 26
#define RIL_REQUEST_SETUP_DATA_CALL 27
#define RIL_REQUEST_SIM_IO 28
#define RIL_REQUEST_SEND_USSD 29
#define RIL_REQUEST_CANCEL_USSD 30
#define RIL_REQUEST_GET_CLIR 31
#define RIL_REQUEST_SET_CLIR 32
#define RIL_REQUEST_QUERY_CALL_FORWARD_STATUS 33
#define RIL_REQUEST_SET_CALL_FORWARD 34
#define RIL_REQUEST_QUERY_CALL_WAITING 35
#define RIL_REQUEST_SET_CALL_WAITING 36
#define RIL_REQUEST_SMS_ACKNOWLEDGE 37
#define RIL_REQUEST_GET_IMEI 38
#define RIL_REQUEST_GET_IMEISV 39
#define RIL_REQUEST_ANSWER 40
#define RIL_REQUEST_DEACTIVATE_DATA_CALL 41
#define RIL_REQUEST_QUERY_FACILITY_LOCK 42
#define RIL_REQUEST_SET_FACILITY_LOCK 43
#define RIL_REQUEST_CHANGE_BARRING_PASSWORD 44
#define RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE 45
#define RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC 46
#define RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL 47
#define RIL_REQUEST_QUERY_AVAILABLE_NETWORKS 48
#define RIL_REQUEST_DTMF_START 49
#define RIL_REQUEST_DTMF_STOP 50
#define RIL_REQUEST_BASEBAND_VERSION 51
#define RIL_REQUEST_SEPARATE_CONNECTION 52
#define RIL_REQUEST_SET_MUTE 53
#define RIL_REQUEST_GET_MUTE 54
#define RIL_REQUEST_QUERY_CLIP 55
#define RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE 56
#define RIL_REQUEST_DATA_CALL_LIST 57
#define RIL_REQUEST_RESET_RADIO 58
#define RIL_REQUEST_OEM_HOOK_RAW 59
#define RIL_REQUEST_OEM_HOOK_STRINGS 60
#define RIL_REQUEST_SCREEN_STATE 61
#define RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION 62
#define RIL_REQUEST_WRITE_SMS_TO_SIM 63
#define RIL_REQUEST_DELETE_SMS_ON_SIM 64
#define RIL_REQUEST_SET_BAND_MODE 65
#define RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE 66
#define RIL_REQUEST_STK_GET_PROFILE 67
#define RIL_REQUEST_STK_SET_PROFILE 68
#define RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND 69
#define RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE 70
#define RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM 71
#define RIL_REQUEST_EXPLICIT_CALL_TRANSFER 72
#define RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE 73
#define RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE 74
#define RIL_REQUEST_GET_NEIGHBORING_CELL_IDS 75
#define RIL_REQUEST_SET_LOCATION_UPDATES 76
#define RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE 77
#define RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE 78
#define RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE 79
#define RIL_REQUEST_SET_TTY_MODE 80
#define RIL_REQUEST_QUERY_TTY_MODE 81
#define RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE 82
#define RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE 83
#define RIL_REQUEST_CDMA_FLASH 84
#define RIL_REQUEST_CDMA_BURST_DTMF 85
#define RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY 86
#define RIL_REQUEST_CDMA_SEND_SMS 87
#define RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE 88
#define RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG 89
#define RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG 90
#define RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION 91
#define RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG 92
#define RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG 93
#define RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION 94
#define RIL_REQUEST_CDMA_SUBSCRIPTION 95
#define RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM 96
#define RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM 97
#define RIL_REQUEST_DEVICE_IDENTITY 98
#define RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE 99
#define RIL_REQUEST_GET_SMSC_ADDRESS 100
#define RIL_REQUEST_SET_SMSC_ADDRESS 101
#define RIL_REQUEST_REPORT_SMS_MEMORY_STATUS 102
#define RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING 103
#define RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE 104
#define RIL_REQUEST_ISIM_AUTHENTICATION 105
#define RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU 106
#define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
#define RIL_REQUEST_VOICE_RADIO_TECH 108
#define RIL_REQUEST_GET_CELL_INFO_LIST 109
#define RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE 110
#define RIL_REQUEST_SET_INITIAL_ATTACH_APN 111
#define RIL_REQUEST_IMS_REGISTRATION_STATE 112
#define RIL_REQUEST_IMS_SEND_SMS 113
#define RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC 114
#define RIL_REQUEST_SIM_OPEN_CHANNEL 115
#define RIL_REQUEST_SIM_CLOSE_CHANNEL 116
#define RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL 117
#define RIL_REQUEST_NV_READ_ITEM 118
#define RIL_REQUEST_NV_WRITE_ITEM 119
#define RIL_REQUEST_NV_WRITE_CDMA_PRL 120
#define RIL_REQUEST_NV_RESET_CONFIG 121
/* SET_UICC_SUBSCRIPTION was 115 in v9 and 122 in v10 and later */
#define RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION 115
#define RIL_REQUEST_SET_UICC_SUBSCRIPTION 122
#define RIL_REQUEST_ALLOW_DATA 123
#define RIL_REQUEST_GET_HARDWARE_CONFIG 124
#define RIL_REQUEST_SIM_AUTHENTICATION 125
#define RIL_REQUEST_GET_DC_RT_INFO 126
#define RIL_REQUEST_SET_DC_RT_INFO_RATE 127
#define RIL_REQUEST_SET_DATA_PROFILE 128
#define RIL_REQUEST_SHUTDOWN 129
#define RIL_REQUEST_GET_RADIO_CAPABILITY 130
#define RIL_REQUEST_SET_RADIO_CAPABILITY 131
/* RIL Unsolicited Messages, rild -> ofono */
#define RIL_UNSOL_RESPONSE_BASE 1000
#define RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED 1000
#define RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 1001
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 1002
#define RIL_UNSOL_RESPONSE_NEW_SMS 1003
#define RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT 1004
#define RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM 1005
#define RIL_UNSOL_ON_USSD 1006
#define RIL_UNSOL_ON_USSD_REQUEST 1007
#define RIL_UNSOL_NITZ_TIME_RECEIVED 1008
#define RIL_UNSOL_SIGNAL_STRENGTH 1009
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 1010
#define RIL_UNSOL_SUPP_SVC_NOTIFICATION 1011
#define RIL_UNSOL_STK_SESSION_END 1012
#define RIL_UNSOL_STK_PROACTIVE_COMMAND 1013
#define RIL_UNSOL_STK_EVENT_NOTIFY 1014
#define RIL_UNSOL_STK_CALL_SETUP 1015
#define RIL_UNSOL_SIM_SMS_STORAGE_FULL 1016
#define RIL_UNSOL_SIM_REFRESH 1017
#define RIL_UNSOL_CALL_RING 1018
#define RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 1019
#define RIL_UNSOL_RESPONSE_CDMA_NEW_SMS 1020
#define RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS 1021
#define RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL 1022
#define RIL_UNSOL_RESTRICTED_STATE_CHANGED 1023
#define RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE 1024
#define RIL_UNSOL_CDMA_CALL_WAITING 1025
#define RIL_UNSOL_CDMA_OTA_PROVISION_STATUS 1026
#define RIL_UNSOL_CDMA_INFO_REC 1027
#define RIL_UNSOL_OEM_HOOK_RAW 1028
#define RIL_UNSOL_RINGBACK_TONE 1029
#define RIL_UNSOL_RESEND_INCALL_MUTE 1030
#define RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED 1031
#define RIL_UNSOL_CDMA_PRL_CHANGED 1032
#define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033
#define RIL_UNSOL_RIL_CONNECTED 1034
#define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035
#define RIL_UNSOL_CELL_INFO_LIST 1036
#define RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED 1037
#define RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED 1038
#define RIL_UNSOL_SRVCC_STATE_NOTIFY 1039
#define RIL_UNSOL_HARDWARE_CONFIG_CHANGED 1040
#define RIL_UNSOL_DC_RT_INFO_CHANGED 1041
#define RIL_UNSOL_RADIO_CAPABILITY 1042
#define RIL_UNSOL_ON_SS 1043
#define RIL_UNSOL_STK_CC_ALPHA_NOTIFY 1044
/* A special request, ofono -> rild */
#define RIL_RESPONSE_ACKNOWLEDGEMENT 800
/* Suplementary services Service class*/ /* Suplementary services Service class*/
#define SERVICE_CLASS_NONE 0 #define SERVICE_CLASS_NONE 0

View File

@@ -76,12 +76,6 @@ enum ril_data_priv_flags {
typedef GObjectClass RilDataClass; typedef GObjectClass RilDataClass;
typedef struct ril_data RilData; typedef struct ril_data RilData;
enum ril_data_io_event_id {
IO_EVENT_DATA_CALL_LIST_CHANGED,
IO_EVENT_RESTRICTED_STATE_CHANGED,
IO_EVENT_COUNT
};
enum ril_data_settings_event_id { enum ril_data_settings_event_id {
SETTINGS_EVENT_IMSI_CHANGED, SETTINGS_EVENT_IMSI_CHANGED,
SETTINGS_EVENT_PREF_MODE, SETTINGS_EVENT_PREF_MODE,
@@ -100,10 +94,8 @@ struct ril_data_priv {
struct ril_radio *radio; struct ril_radio *radio;
struct ril_network *network; struct ril_network *network;
struct ril_data_manager *dm; struct ril_data_manager *dm;
struct ril_vendor_hook *vendor_hook;
enum ril_data_priv_flags flags; enum ril_data_priv_flags flags;
enum ril_restricted_state restricted_state; struct ril_vendor_hook *vendor_hook;
struct ril_data_request *req_queue; struct ril_data_request *req_queue;
struct ril_data_request *pending_req; struct ril_data_request *pending_req;
@@ -112,9 +104,8 @@ struct ril_data_priv {
guint slot; guint slot;
char *log_prefix; char *log_prefix;
guint query_id; guint query_id;
gulong io_event_id[IO_EVENT_COUNT]; gulong io_event_id;
gulong settings_event_id[SETTINGS_EVENT_COUNT]; gulong settings_event_id[SETTINGS_EVENT_COUNT];
GHashTable* grab;
}; };
enum ril_data_signal { enum ril_data_signal {
@@ -186,7 +177,7 @@ struct ril_data_request_allow_data {
static void ril_data_manager_check_data(struct ril_data_manager *dm); static void ril_data_manager_check_data(struct ril_data_manager *dm);
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm); static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);
static void ril_data_call_deact_cid(struct ril_data *data, int cid);
static void ril_data_power_update(struct ril_data *self); static void ril_data_power_update(struct ril_data *self);
static void ril_data_signal_emit(struct ril_data *self, enum ril_data_signal id) static void ril_data_signal_emit(struct ril_data *self, enum ril_data_signal id)
{ {
@@ -546,10 +537,6 @@ struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
static void ril_data_set_calls(struct ril_data *self, static void ril_data_set_calls(struct ril_data *self,
struct ril_data_call_list *list) struct ril_data_call_list *list)
{ {
struct ril_data_priv *priv = self->priv;
GHashTableIter it;
gpointer key;
if (!ril_data_call_list_equal(self->data_calls, list)) { if (!ril_data_call_list_equal(self->data_calls, list)) {
DBG("data calls changed"); DBG("data calls changed");
ril_data_call_list_free(self->data_calls); ril_data_call_list_free(self->data_calls);
@@ -558,63 +545,6 @@ static void ril_data_set_calls(struct ril_data *self,
} else { } else {
ril_data_call_list_free(list); ril_data_call_list_free(list);
} }
/* Clean up the grab table */
g_hash_table_iter_init(&it, priv->grab);
while (g_hash_table_iter_next(&it, &key, NULL)) {
const int cid = GPOINTER_TO_INT(key);
if (!ril_data_call_find(self->data_calls, cid)) {
g_hash_table_iter_remove(&it);
}
}
if (self->data_calls) {
GSList *l;
/* Disconnect stray calls (one at a time) */
for (l = self->data_calls->calls; l; l = l->next) {
struct ril_data_call *dc = l->data;
key = GINT_TO_POINTER(dc->cid);
if (!g_hash_table_contains(priv->grab, key)) {
DBG_(self, "stray call %u", dc->cid);
ril_data_call_deact_cid(self, dc->cid);
break;
}
}
}
}
static void ril_data_check_allowed(struct ril_data *self, gboolean was_allowed)
{
if (ril_data_allowed(self) != was_allowed) {
ril_data_signal_emit(self, SIGNAL_ALLOW_CHANGED);
}
}
static void ril_data_restricted_state_changed_cb(GRilIoChannel *io, guint event,
const void *data, guint len, void *user_data)
{
struct ril_data *self = RIL_DATA(user_data);
GRilIoParser rilp;
guint32 count, state;
GASSERT(event == RIL_UNSOL_RESTRICTED_STATE_CHANGED);
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_uint32(&rilp, &count) && count == 1 &&
grilio_parser_get_uint32(&rilp, &state) &&
grilio_parser_at_end(&rilp)) {
struct ril_data_priv *priv = self->priv;
if (priv->restricted_state != state) {
const gboolean was_allowed = ril_data_allowed(self);
DBG_(self, "restricted state 0x%02x", state);
priv->restricted_state = state;
ril_data_check_allowed(self, was_allowed);
}
}
} }
static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event, static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
@@ -1114,11 +1044,6 @@ static struct ril_data_request *ril_data_call_deact_new(struct ril_data *data,
return req; return req;
} }
static void ril_data_call_deact_cid(struct ril_data *data, int cid)
{
ril_data_request_queue(ril_data_call_deact_new(data, cid, NULL, NULL));
}
/*==========================================================================* /*==========================================================================*
* ril_data_allow_request * ril_data_allow_request
*==========================================================================*/ *==========================================================================*/
@@ -1145,7 +1070,9 @@ static void ril_data_allow_cb(GRilIoChannel *io, int ril_status,
DBG_(data, "data off"); DBG_(data, "data off");
} }
ril_data_check_allowed(data, was_allowed); if (ril_data_allowed(data) != was_allowed) {
ril_data_signal_emit(data, SIGNAL_ALLOW_CHANGED);
}
} }
ril_data_request_finish(req); ril_data_request_finish(req);
@@ -1261,15 +1188,9 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
priv->radio = ril_radio_ref(radio); priv->radio = ril_radio_ref(radio);
priv->network = ril_network_ref(network); priv->network = ril_network_ref(network);
priv->vendor_hook = ril_vendor_hook_ref(vendor_hook); priv->vendor_hook = ril_vendor_hook_ref(vendor_hook);
priv->io_event_id = grilio_channel_add_unsol_event_handler(io,
priv->io_event_id[IO_EVENT_DATA_CALL_LIST_CHANGED] =
grilio_channel_add_unsol_event_handler(io,
ril_data_call_list_changed_cb, ril_data_call_list_changed_cb,
RIL_UNSOL_DATA_CALL_LIST_CHANGED, self); RIL_UNSOL_DATA_CALL_LIST_CHANGED, self);
priv->io_event_id[IO_EVENT_RESTRICTED_STATE_CHANGED] =
grilio_channel_add_unsol_event_handler(io,
ril_data_restricted_state_changed_cb,
RIL_UNSOL_RESTRICTED_STATE_CHANGED, self);
priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] = priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] =
ril_sim_settings_add_imsi_changed_handler(settings, ril_sim_settings_add_imsi_changed_handler(settings,
@@ -1343,8 +1264,6 @@ void ril_data_unref(struct ril_data *self)
gboolean ril_data_allowed(struct ril_data *self) gboolean ril_data_allowed(struct ril_data *self)
{ {
return G_LIKELY(self) && return G_LIKELY(self) &&
(self->priv->restricted_state &
RIL_RESTRICTED_STATE_PS_ALL) == 0 &&
(self->priv->flags & (self->priv->flags &
(RIL_DATA_FLAG_ALLOWED | RIL_DATA_FLAG_ON)) == (RIL_DATA_FLAG_ALLOWED | RIL_DATA_FLAG_ON)) ==
(RIL_DATA_FLAG_ALLOWED | RIL_DATA_FLAG_ON); (RIL_DATA_FLAG_ALLOWED | RIL_DATA_FLAG_ON);
@@ -1359,7 +1278,9 @@ static void ril_data_deactivate_all(struct ril_data *self)
struct ril_data_call *call = l->data; struct ril_data_call *call = l->data;
if (call->status == PDP_FAIL_NONE) { if (call->status == PDP_FAIL_NONE) {
DBG_(self, "deactivating call %u", call->cid); DBG_(self, "deactivating call %u", call->cid);
ril_data_call_deact_cid(self, call->cid); ril_data_request_queue(
ril_data_call_deact_new(self,
call->cid, NULL, NULL));
} }
} }
} }
@@ -1427,7 +1348,9 @@ static void ril_data_disallow(struct ril_data *self)
ril_data_power_update(self); ril_data_power_update(self);
} }
ril_data_check_allowed(self, was_allowed); if (ril_data_allowed(self) != was_allowed) {
ril_data_signal_emit(self, SIGNAL_ALLOW_CHANGED);
}
} }
static void ril_data_max_speed_cb(gpointer data, gpointer max_speed) static void ril_data_max_speed_cb(gpointer data, gpointer max_speed)
@@ -1526,39 +1449,12 @@ struct ril_data_request *ril_data_call_deactivate(struct ril_data *self,
return req; return req;
} }
gboolean ril_data_call_grab(struct ril_data *self, int cid, void *cookie)
{
if (self && cookie && ril_data_call_find(self->data_calls, cid)) {
struct ril_data_priv *priv = self->priv;
gpointer key = GINT_TO_POINTER(cid);
void *prev = g_hash_table_lookup(priv->grab, key);
if (!prev) {
g_hash_table_insert(priv->grab, key, cookie);
return TRUE;
} else {
return (prev == cookie);
}
}
return FALSE;
}
void ril_data_call_release(struct ril_data *self, int cid, void *cookie)
{
if (self && cookie) {
struct ril_data_priv *priv = self->priv;
g_hash_table_remove(priv->grab, GUINT_TO_POINTER(cid));
}
}
static void ril_data_init(struct ril_data *self) static void ril_data_init(struct ril_data *self)
{ {
struct ril_data_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self, struct ril_data_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
RIL_DATA_TYPE, struct ril_data_priv); RIL_DATA_TYPE, struct ril_data_priv);
self->priv = priv; self->priv = priv;
priv->grab = g_hash_table_new(g_direct_hash, g_direct_equal);
} }
static void ril_data_dispose(GObject *object) static void ril_data_dispose(GObject *object)
@@ -1572,7 +1468,7 @@ static void ril_data_dispose(GObject *object)
ril_sim_settings_remove_handlers(settings, priv->settings_event_id, ril_sim_settings_remove_handlers(settings, priv->settings_event_id,
G_N_ELEMENTS(priv->settings_event_id)); G_N_ELEMENTS(priv->settings_event_id));
grilio_channel_remove_all_handlers(priv->io, priv->io_event_id); grilio_channel_remove_handlers(priv->io, &priv->io_event_id, 1);
grilio_queue_cancel_all(priv->q, FALSE); grilio_queue_cancel_all(priv->q, FALSE);
priv->query_id = 0; priv->query_id = 0;
@@ -1586,7 +1482,6 @@ static void ril_data_dispose(GObject *object)
dm->data_list = g_slist_remove(dm->data_list, self); dm->data_list = g_slist_remove(dm->data_list, self);
ril_data_manager_check_data(dm); ril_data_manager_check_data(dm);
g_hash_table_destroy(priv->grab);
G_OBJECT_CLASS(ril_data_parent_class)->dispose(object); G_OBJECT_CLASS(ril_data_parent_class)->dispose(object);
} }

View File

@@ -123,9 +123,6 @@ struct ril_data_request *ril_data_call_deactivate(struct ril_data *data,
void ril_data_request_detach(struct ril_data_request *req); void ril_data_request_detach(struct ril_data_request *req);
void ril_data_request_cancel(struct ril_data_request *req); void ril_data_request_cancel(struct ril_data_request *req);
gboolean ril_data_call_grab(struct ril_data *data, int cid, void *cookie);
void ril_data_call_release(struct ril_data *data, int cid, void *cookie);
void ril_data_call_free(struct ril_data_call *call); void ril_data_call_free(struct ril_data_call *call);
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call); struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list, struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,

View File

@@ -88,7 +88,6 @@ static int ril_gprs_context_address_family(const char *addr)
static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd) static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
{ {
if (gcd->active_call) { if (gcd->active_call) {
ril_data_call_release(gcd->data, gcd->active_call->cid, gcd);
ril_data_call_free(gcd->active_call); ril_data_call_free(gcd->active_call);
gcd->active_call = NULL; gcd->active_call = NULL;
} }
@@ -112,7 +111,6 @@ static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
gcd->mtu_watch = mtu_watch_new(MAX_MTU); gcd->mtu_watch = mtu_watch_new(MAX_MTU);
} }
mtu_watch_set_ifname(gcd->mtu_watch, call->ifname); mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
ril_data_call_grab(gcd->data, call->cid, gcd);
} else { } else {
ril_gprs_context_free_active_call(gcd); ril_gprs_context_free_active_call(gcd);
} }

View File

@@ -454,10 +454,8 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
ofono_modem_set_data(ofono, md); ofono_modem_set_data(ofono, md);
err = ofono_modem_register(ofono); err = ofono_modem_register(ofono);
if (!err) { if (!err) {
ril_radio_power_cycle(modem->radio);
GASSERT(io->connected); GASSERT(io->connected);
if (config->radio_power_cycle) {
ril_radio_power_cycle(modem->radio);
}
/* /*
* ofono_modem_reset sets Powered to TRUE without * ofono_modem_reset sets Powered to TRUE without

View File

@@ -61,8 +61,6 @@ struct ril_netreg_cbd {
#define ril_netreg_cbd_free g_free #define ril_netreg_cbd_free g_free
#define DBG_(nd,fmt,args...) DBG("%s" fmt, (nd)->log_prefix, ##args)
static inline struct ril_netreg *ril_netreg_get_data(struct ofono_netreg *ofono) static inline struct ril_netreg *ril_netreg_get_data(struct ofono_netreg *ofono)
{ {
return ofono ? ofono_netreg_get_data(ofono) : NULL; return ofono ? ofono_netreg_get_data(ofono) : NULL;
@@ -111,7 +109,7 @@ static gboolean ril_netreg_status_notify_cb(gpointer user_data)
struct ril_netreg *nd = user_data; struct ril_netreg *nd = user_data;
const struct ril_registration_state *reg = &nd->network->voice; const struct ril_registration_state *reg = &nd->network->voice;
DBG_(nd, ""); DBG("%s", nd->log_prefix);
GASSERT(nd->notify_id); GASSERT(nd->notify_id);
nd->notify_id = 0; nd->notify_id = 0;
ofono_netreg_status_notify(nd->netreg, ofono_netreg_status_notify(nd->netreg,
@@ -126,9 +124,9 @@ static void ril_netreg_status_notify(struct ril_network *net, void *user_data)
/* Coalesce multiple notifications into one */ /* Coalesce multiple notifications into one */
if (nd->notify_id) { if (nd->notify_id) {
DBG_(nd, "notification aready queued"); DBG("%snotification aready queued", nd->log_prefix);
} else { } else {
DBG_(nd, "queuing notification"); DBG("%squeuing notification", nd->log_prefix);
nd->notify_id = g_idle_add(ril_netreg_status_notify_cb, nd); nd->notify_id = g_idle_add(ril_netreg_status_notify_cb, nd);
} }
} }
@@ -140,7 +138,7 @@ static void ril_netreg_registration_status(struct ofono_netreg *netreg,
const struct ril_registration_state *reg = &nd->network->voice; const struct ril_registration_state *reg = &nd->network->voice;
struct ofono_error error; struct ofono_error error;
DBG_(nd, ""); DBG("%s", nd->log_prefix);
cb(ril_error_ok(&error), cb(ril_error_ok(&error),
ril_netreg_check_status(nd, reg->status), ril_netreg_check_status(nd, reg->status),
reg->lac, reg->ci, reg->access_tech, data); reg->lac, reg->ci, reg->access_tech, data);
@@ -153,7 +151,7 @@ static gboolean ril_netreg_current_operator_cb(void *user_data)
ofono_netreg_operator_cb_t cb = cbd->cb.operator; ofono_netreg_operator_cb_t cb = cbd->cb.operator;
struct ofono_error error; struct ofono_error error;
DBG_(nd, ""); DBG("%s", nd->log_prefix);
GASSERT(nd->current_operator_id); GASSERT(nd->current_operator_id);
nd->current_operator_id = 0; nd->current_operator_id = 0;
@@ -399,7 +397,7 @@ static void ril_netreg_strength_notify(GRilIoChannel *io, guint ril_event,
GASSERT(ril_event == RIL_UNSOL_SIGNAL_STRENGTH); GASSERT(ril_event == RIL_UNSOL_SIGNAL_STRENGTH);
strength = ril_netreg_get_signal_strength(data, len); strength = ril_netreg_get_signal_strength(data, len);
DBG_(nd, "%d", strength); DBG("%d", strength);
ofono_netreg_strength_notify(nd->netreg, strength); ofono_netreg_strength_notify(nd->netreg, strength);
} }
@@ -447,7 +445,7 @@ static void ril_netreg_nitz_notify(GRilIoChannel *io, guint ril_event,
grilio_parser_init(&rilp, data, len); grilio_parser_init(&rilp, data, len);
nitz = grilio_parser_get_utf8(&rilp); nitz = grilio_parser_get_utf8(&rilp);
DBG_(nd, "%s", nitz); DBG("%s", nitz);
/* /*
* Format: yy/mm/dd,hh:mm:ss(+/-)tz[,ds] * Format: yy/mm/dd,hh:mm:ss(+/-)tz[,ds]
@@ -514,11 +512,10 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
{ {
struct ril_modem *modem = data; struct ril_modem *modem = data;
struct ril_netreg *nd = g_new0(struct ril_netreg, 1); struct ril_netreg *nd = g_new0(struct ril_netreg, 1);
guint slot = ril_modem_slot(modem);
nd->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ? DBG("[%u] %p", slot, netreg);
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup(""); nd->log_prefix = g_strdup_printf("%s_%u ", RILMODEM_DRIVER, slot);
DBG_(nd, "%p", netreg);
nd->io = grilio_channel_ref(ril_modem_io(modem)); nd->io = grilio_channel_ref(ril_modem_io(modem));
nd->q = grilio_queue_new(nd->io); nd->q = grilio_queue_new(nd->io);
nd->network = ril_network_ref(modem->network); nd->network = ril_network_ref(modem->network);
@@ -532,8 +529,9 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
static void ril_netreg_remove(struct ofono_netreg *netreg) static void ril_netreg_remove(struct ofono_netreg *netreg)
{ {
struct ril_netreg *nd = ril_netreg_get_data(netreg); struct ril_netreg *nd = ril_netreg_get_data(netreg);
unsigned int i;
DBG_(nd, "%p", netreg); DBG("%p", netreg);
grilio_queue_cancel_all(nd->q, FALSE); grilio_queue_cancel_all(nd->q, FALSE);
ofono_netreg_set_data(netreg, NULL); ofono_netreg_set_data(netreg, NULL);
@@ -549,10 +547,14 @@ static void ril_netreg_remove(struct ofono_netreg *netreg)
g_source_remove(nd->current_operator_id); g_source_remove(nd->current_operator_id);
} }
ril_network_remove_all_handlers(nd->network, nd->network_event_id); for (i=0; i<G_N_ELEMENTS(nd->network_event_id); i++) {
ril_network_remove_handler(nd->network, nd->network_event_id[i]);
}
ril_network_unref(nd->network); ril_network_unref(nd->network);
grilio_channel_remove_all_handlers(nd->io, nd->ril_event_id); grilio_channel_remove_handlers(nd->io, nd->ril_event_id,
G_N_ELEMENTS(nd->ril_event_id));
grilio_channel_unref(nd->io); grilio_channel_unref(nd->io);
grilio_queue_unref(nd->q); grilio_queue_unref(nd->q);
g_free(nd->log_prefix); g_free(nd->log_prefix);

View File

@@ -47,12 +47,6 @@ enum ril_network_radio_event {
RADIO_EVENT_COUNT RADIO_EVENT_COUNT
}; };
enum ril_network_sim_events {
SIM_EVENT_STATUS_CHANGED,
SIM_EVENT_IO_ACTIVE_CHANGED,
SIM_EVENT_COUNT
};
enum ril_network_unsol_event { enum ril_network_unsol_event {
UNSOL_EVENT_NETWORK_STATE, UNSOL_EVENT_NETWORK_STATE,
UNSOL_EVENT_RADIO_CAPABILITY, UNSOL_EVENT_RADIO_CAPABILITY,
@@ -63,10 +57,8 @@ struct ril_network_priv {
GRilIoChannel *io; GRilIoChannel *io;
GRilIoQueue *q; GRilIoQueue *q;
struct ril_radio *radio; struct ril_radio *radio;
struct ril_sim_card *simcard; struct ril_sim_card *sim_card;
int rat; int rat;
int lte_network_mode;
int network_mode_timeout;
char *log_prefix; char *log_prefix;
guint operator_poll_id; guint operator_poll_id;
guint voice_poll_id; guint voice_poll_id;
@@ -76,8 +68,8 @@ struct ril_network_priv {
gulong set_rat_id; gulong set_rat_id;
gulong unsol_event_id[UNSOL_EVENT_COUNT]; gulong unsol_event_id[UNSOL_EVENT_COUNT];
gulong settings_event_id; gulong settings_event_id;
gulong sim_status_event_id;
gulong radio_event_id[RADIO_EVENT_COUNT]; gulong radio_event_id[RADIO_EVENT_COUNT];
gulong simcard_event_id[SIM_EVENT_COUNT];
struct ofono_network_operator operator; struct ofono_network_operator operator;
gboolean assert_rat; gboolean assert_rat;
}; };
@@ -119,8 +111,7 @@ G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_UMTS > OFONO_RADIO_ACCESS_MODE_GSM);
G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_LTE > OFONO_RADIO_ACCESS_MODE_UMTS); G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_LTE > OFONO_RADIO_ACCESS_MODE_UMTS);
static void ril_network_query_pref_mode(struct ril_network *self); static void ril_network_query_pref_mode(struct ril_network *self);
static void ril_network_check_pref_mode(struct ril_network *self, static void ril_network_set_pref_mode(struct ril_network *self, int rat);
gboolean immediate);
static void ril_network_emit(struct ril_network *self, static void ril_network_emit(struct ril_network *self,
enum ril_network_signal sig) enum ril_network_signal sig)
@@ -217,11 +208,11 @@ static gboolean ril_network_parse_response(struct ril_network *self,
reg->max_calls = 2; reg->max_calls = 2;
} }
if (!gutil_parse_int(slac, 16, &reg->lac)) { if (!ril_parse_int(slac, 16, &reg->lac)) {
reg->lac = -1; reg->lac = -1;
} }
if (!gutil_parse_int(sci, 16, &reg->ci)) { if (!ril_parse_int(sci, 16, &reg->ci)) {
reg->ci = -1; reg->ci = -1;
} }
@@ -457,7 +448,7 @@ static int ril_network_mode_to_rat(struct ril_network *self,
case OFONO_RADIO_ACCESS_MODE_ANY: case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_LTE: case OFONO_RADIO_ACCESS_MODE_LTE:
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) { if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
return self->priv->lte_network_mode; return PREF_NET_TYPE_LTE_GSM_WCDMA;
} }
/* no break */ /* no break */
default: default:
@@ -506,28 +497,37 @@ static gboolean ril_network_can_set_pref_mode(struct ril_network *self)
{ {
struct ril_network_priv *priv = self->priv; struct ril_network_priv *priv = self->priv;
/* return priv->radio->online && ril_sim_card_ready(priv->sim_card);
* With some modems an attempt to set rat significantly slows
* down SIM I/O, let's avoid that.
*/
return priv->radio->online && ril_sim_card_ready(priv->simcard) &&
!priv->simcard->sim_io_active &&
!priv->timer[TIMER_SET_RAT_HOLDOFF] ;
} }
static gboolean ril_network_set_rat_holdoff_cb(gpointer user_data) static gboolean ril_network_set_rat_holdoff_cb(gpointer user_data)
{ {
struct ril_network *self = RIL_NETWORK(user_data); struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv; struct ril_network_priv *priv = self->priv;
const int rat = ril_network_pref_mode_expected(self);
DBG_(self, "rat mode %d, expected %d", priv->rat, rat);
GASSERT(priv->timer[TIMER_SET_RAT_HOLDOFF]); GASSERT(priv->timer[TIMER_SET_RAT_HOLDOFF]);
priv->timer[TIMER_SET_RAT_HOLDOFF] = 0; priv->timer[TIMER_SET_RAT_HOLDOFF] = 0;
ril_network_check_pref_mode(self, FALSE); /*
* Don't retry the request if modem is offline or SIM card isn't
* ready, to avoid spamming system log with error messages. Radio
* and SIM card state change callbacks will schedule a new check
* when it's appropriate.
*/
if (priv->rat != rat || priv->assert_rat) {
if (ril_network_can_set_pref_mode(self)) {
ril_network_set_pref_mode(self, rat);
} else {
DBG_(self, "giving up");
}
}
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void ril_network_set_rat_cb(GRilIoChannel *io, int status, static void ril_network_set_pref_mode_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_network *self = RIL_NETWORK(user_data); struct ril_network *self = RIL_NETWORK(user_data);
@@ -542,53 +542,33 @@ static void ril_network_set_rat_cb(GRilIoChannel *io, int status,
ril_network_query_pref_mode(self); ril_network_query_pref_mode(self);
} }
static void ril_network_set_rat(struct ril_network *self, int rat)
{
struct ril_network_priv *priv = self->priv;
if (!priv->set_rat_id && priv->radio->online &&
ril_sim_card_ready(priv->simcard) &&
/*
* With some modems an attempt to set rat significantly
* slows down SIM I/O, let's avoid that.
*/
!priv->simcard->sim_io_active &&
!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
GRilIoRequest *req = grilio_request_sized_new(8);
DBG_(self, "setting rat mode %d", rat);
grilio_request_append_int32(req, 1); /* count */
grilio_request_append_int32(req, rat);
grilio_request_set_timeout(req, priv->network_mode_timeout);
priv->set_rat_id = grilio_queue_send_request_full(priv->q, req,
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
ril_network_set_rat_cb, NULL, self);
grilio_request_unref(req);
/* We have submitted the request, clear the assertion flag */
priv->assert_rat = FALSE;
/* And don't do it too often */
priv->timer[TIMER_SET_RAT_HOLDOFF] =
g_timeout_add_seconds(SET_PREF_MODE_HOLDOFF_SEC,
ril_network_set_rat_holdoff_cb, self);
} else {
DBG_(self, "need to set rat mode %d", rat);
}
}
static void ril_network_set_pref_mode(struct ril_network *self, int rat) static void ril_network_set_pref_mode(struct ril_network *self, int rat)
{ {
struct ril_network_priv *priv = self->priv; struct ril_network_priv *priv = self->priv;
GRilIoRequest *req = grilio_request_sized_new(8);
if (priv->rat != rat || priv->assert_rat) { DBG_(self, "setting rat mode %d", rat);
ril_network_set_rat(self, rat); grilio_request_append_int32(req, 1); /* Number of params */
} grilio_request_append_int32(req, rat);
grilio_queue_cancel_request(priv->q, priv->set_rat_id, FALSE);
priv->set_rat_id = grilio_queue_send_request_full(priv->q, req,
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
ril_network_set_pref_mode_cb, NULL, self);
grilio_request_unref(req);
/* We have submitted the request, clear the assertion flag */
priv->assert_rat = FALSE;
/* Don't do it too often */
GASSERT(!priv->timer[TIMER_SET_RAT_HOLDOFF]);
priv->timer[TIMER_SET_RAT_HOLDOFF] =
g_timeout_add_seconds(SET_PREF_MODE_HOLDOFF_SEC,
ril_network_set_rat_holdoff_cb, self);
} }
static void ril_network_check_pref_mode(struct ril_network *self, static void ril_network_check_pref_mode(struct ril_network *self,
gboolean immediate) gboolean force)
{ {
struct ril_network_priv *priv = self->priv; struct ril_network_priv *priv = self->priv;
const int rat = ril_network_pref_mode_expected(self); const int rat = ril_network_pref_mode_expected(self);
@@ -600,14 +580,10 @@ static void ril_network_check_pref_mode(struct ril_network *self,
* ril_network_pref_mode_changed_cb and is meant * ril_network_pref_mode_changed_cb and is meant
* to force radio tech check right now. * to force radio tech check right now.
*/ */
immediate = TRUE; force = TRUE;
} }
if (priv->rat != rat) { if (priv->rat == rat || force) {
DBG_(self, "rat mode %d, expected %d", priv->rat, rat);
}
if (immediate) {
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF); ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
} }
@@ -850,9 +826,8 @@ static void ril_network_sim_status_changed_cb(struct ril_sim_card *sc,
struct ril_network *ril_network_new(const char *path, GRilIoChannel *io, struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio, const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *simcard, struct ril_sim_card *sim_card,
struct ril_sim_settings *settings, struct ril_sim_settings *settings)
const struct ril_slot_config *config)
{ {
struct ril_network *self = g_object_new(RIL_NETWORK_TYPE, NULL); struct ril_network *self = g_object_new(RIL_NETWORK_TYPE, NULL);
struct ril_network_priv *priv = self->priv; struct ril_network_priv *priv = self->priv;
@@ -861,16 +836,10 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
priv->io = grilio_channel_ref(io); priv->io = grilio_channel_ref(io);
priv->q = grilio_queue_new(priv->io); priv->q = grilio_queue_new(priv->io);
priv->radio = ril_radio_ref(radio); priv->radio = ril_radio_ref(radio);
priv->simcard = ril_sim_card_ref(simcard); priv->sim_card = ril_sim_card_ref(sim_card);
priv->log_prefix = (log_prefix && log_prefix[0]) ? priv->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup(""); g_strconcat(log_prefix, " ", NULL) : g_strdup("");
DBG_(self, ""); DBG_(self, "");
/* Copy relevant config values */
priv->lte_network_mode = config->lte_network_mode;
priv->network_mode_timeout = config->network_mode_timeout;
/* Register listeners */
priv->unsol_event_id[UNSOL_EVENT_NETWORK_STATE] = priv->unsol_event_id[UNSOL_EVENT_NETWORK_STATE] =
grilio_channel_add_unsol_event_handler(priv->io, grilio_channel_add_unsol_event_handler(priv->io,
ril_network_state_changed_cb, ril_network_state_changed_cb,
@@ -885,15 +854,12 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
priv->radio_event_id[RADIO_EVENT_ONLINE_CHANGED] = priv->radio_event_id[RADIO_EVENT_ONLINE_CHANGED] =
ril_radio_add_online_changed_handler(priv->radio, ril_radio_add_online_changed_handler(priv->radio,
ril_network_radio_online_cb, self); ril_network_radio_online_cb, self);
priv->simcard_event_id[SIM_EVENT_STATUS_CHANGED] =
ril_sim_card_add_status_changed_handler(priv->simcard,
ril_network_sim_status_changed_cb, self);
priv->simcard_event_id[SIM_EVENT_IO_ACTIVE_CHANGED] =
ril_sim_card_add_sim_io_active_changed_handler(priv->simcard,
ril_network_sim_status_changed_cb, self);
priv->settings_event_id = priv->settings_event_id =
ril_sim_settings_add_pref_mode_changed_handler(settings, ril_sim_settings_add_pref_mode_changed_handler(settings,
ril_network_pref_mode_changed_cb, self); ril_network_pref_mode_changed_cb, self);
priv->sim_status_event_id =
ril_sim_card_add_status_changed_handler(priv->sim_card,
ril_network_sim_status_changed_cb, self);
/* /*
* Query the initial state. Querying network state before the radio * Query the initial state. Querying network state before the radio
@@ -950,13 +916,16 @@ static void ril_network_finalize(GObject *object)
} }
grilio_queue_cancel_all(priv->q, FALSE); grilio_queue_cancel_all(priv->q, FALSE);
grilio_channel_remove_all_handlers(priv->io, priv->unsol_event_id); grilio_channel_remove_handlers(priv->io, priv->unsol_event_id,
G_N_ELEMENTS(priv->unsol_event_id));
grilio_channel_unref(priv->io); grilio_channel_unref(priv->io);
grilio_queue_unref(priv->q); grilio_queue_unref(priv->q);
ril_radio_remove_all_handlers(priv->radio, priv->radio_event_id); ril_radio_remove_all_handlers(priv->radio, priv->radio_event_id);
ril_radio_unref(priv->radio); ril_radio_unref(priv->radio);
ril_sim_card_remove_all_handlers(priv->simcard, priv->simcard_event_id); ril_sim_card_remove_handler(priv->sim_card,
ril_sim_card_unref(priv->simcard); priv->sim_status_event_id);
ril_sim_card_unref(priv->sim_card);
ril_sim_settings_remove_handler(self->settings, ril_sim_settings_remove_handler(self->settings,
priv->settings_event_id); priv->settings_event_id);
ril_sim_settings_unref(self->settings); ril_sim_settings_unref(self->settings);

View File

@@ -48,8 +48,7 @@ typedef void (*ril_network_cb_t)(struct ril_network *net, void *arg);
struct ril_network *ril_network_new(const char *path, GRilIoChannel *io, struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio, const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *sim_card, struct ril_sim_card *sim_card,
struct ril_sim_settings *settings, struct ril_sim_settings *settings);
const struct ril_slot_config *ril_slot_config);
struct ril_network *ril_network_ref(struct ril_network *net); struct ril_network *ril_network_ref(struct ril_network *net);
void ril_network_unref(struct ril_network *net); void ril_network_unref(struct ril_network *net);

View File

@@ -30,11 +30,8 @@
#include <sailfish_manager.h> #include <sailfish_manager.h>
#include <sailfish_watch.h> #include <sailfish_watch.h>
#include <grilio_transport.h>
#include <gutil_ints.h> #include <gutil_ints.h>
#include <gutil_macros.h> #include <gutil_macros.h>
#include <gutil_misc.h>
#include <mce_display.h> #include <mce_display.h>
#include <mce_log.h> #include <mce_log.h>
@@ -51,7 +48,6 @@
#define OFONO_API_SUBJECT_TO_CHANGE #define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h> #include <ofono/plugin.h>
#include <ofono/storage.h> #include <ofono/storage.h>
#include <ofono/ril-transport.h>
#define OFONO_RADIO_ACCESS_MODE_ALL (OFONO_RADIO_ACCESS_MODE_GSM |\ #define OFONO_RADIO_ACCESS_MODE_ALL (OFONO_RADIO_ACCESS_MODE_GSM |\
OFONO_RADIO_ACCESS_MODE_UMTS |\ OFONO_RADIO_ACCESS_MODE_UMTS |\
@@ -67,8 +63,6 @@
#define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2" #define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2"
#define RILMODEM_DEFAULT_SUB "SUB1" #define RILMODEM_DEFAULT_SUB "SUB1"
#define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL #define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL
#define RILMODEM_DEFAULT_LTE_MODE PREF_NET_TYPE_LTE_GSM_WCDMA
#define RILMODEM_DEFAULT_NETWORK_MODE_TIMEOUT (20*1000) /* ms */
#define RILMODEM_DEFAULT_ENABLE_VOICECALL TRUE #define RILMODEM_DEFAULT_ENABLE_VOICECALL TRUE
#define RILMODEM_DEFAULT_ENABLE_CBS TRUE #define RILMODEM_DEFAULT_ENABLE_CBS TRUE
#define RILMODEM_DEFAULT_SLOT 0xffffffff #define RILMODEM_DEFAULT_SLOT 0xffffffff
@@ -83,14 +77,6 @@
#define RILMODEM_DEFAULT_EMPTY_PIN_QUERY TRUE /* optimistic */ #define RILMODEM_DEFAULT_EMPTY_PIN_QUERY TRUE /* optimistic */
#define RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE TRUE /* Qualcomm */ #define RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE TRUE /* Qualcomm */
#define RILMODEM_DEFAULT_LEGACY_IMEI_QUERY FALSE #define RILMODEM_DEFAULT_LEGACY_IMEI_QUERY FALSE
#define RILMODEM_DEFAULT_RADIO_POWER_CYCLE TRUE
#define RILMODEM_DEFAULT_CONFIRM_RADIO_POWER_ON TRUE
#define RILMODEM_DEFAULT_SLOT_FLAGS SAILFISH_SLOT_NO_FLAGS
/* RIL socket transport name and parameters */
#define RIL_TRANSPORT_SOCKET "socket"
#define RIL_TRANSPORT_SOCKET_PATH "path"
#define RIL_TRANSPORT_SOCKET_SUB "sub"
/* /*
* The convention is that the keys which can only appear in the [Settings] * The convention is that the keys which can only appear in the [Settings]
@@ -98,44 +84,38 @@
* modem section (OR in the [Settings] if they apply to all modems) start * modem section (OR in the [Settings] if they apply to all modems) start
* with lower case. * with lower case.
*/ */
#define RILCONF_SETTINGS_EMPTY "EmptyConfig" #define RILCONF_SETTINGS_EMPTY "EmptyConfig"
#define RILCONF_SETTINGS_IDENTITY "Identity" #define RILCONF_SETTINGS_IDENTITY "Identity"
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover" #define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
#define RILCONF_SETTINGS_SET_RADIO_CAP "SetRadioCapability" #define RILCONF_SETTINGS_SET_RADIO_CAP "SetRadioCapability"
#define RILCONF_MODEM_PREFIX "ril_" #define RILCONF_DEV_PREFIX "ril_"
#define RILCONF_PATH_PREFIX "/" RILCONF_MODEM_PREFIX #define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
#define RILCONF_TRANSPORT "transport" #define RILCONF_NAME "name"
#define RILCONF_NAME "name" #define RILCONF_SOCKET "socket"
#define RILCONF_SOCKET "socket" #define RILCONF_SLOT "slot"
#define RILCONF_SLOT "slot" #define RILCONF_SUB "sub"
#define RILCONF_SUB "sub" #define RILCONF_START_TIMEOUT "startTimeout"
#define RILCONF_START_TIMEOUT "startTimeout" #define RILCONF_TIMEOUT "timeout"
#define RILCONF_TIMEOUT "timeout" #define RILCONF_4G "enable4G" /* Deprecated */
#define RILCONF_4G "enable4G" /* Deprecated */ #define RILCONF_ENABLE_VOICECALL "enableVoicecall"
#define RILCONF_ENABLE_VOICECALL "enableVoicecall" #define RILCONF_ENABLE_CBS "enableCellBroadcast"
#define RILCONF_ENABLE_CBS "enableCellBroadcast" #define RILCONF_TECHNOLOGIES "technologies"
#define RILCONF_TECHNOLOGIES "technologies" #define RILCONF_UICC_WORKAROUND "uiccWorkaround"
#define RILCONF_LTE_MODE "lteNetworkMode" #define RILCONF_ECCLIST_FILE "ecclistFile"
#define RILCONF_NETWORK_MODE_TIMEOUT "networkModeTimeout" #define RILCONF_ALLOW_DATA_REQ "allowDataReq"
#define RILCONF_UICC_WORKAROUND "uiccWorkaround" #define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery"
#define RILCONF_ECCLIST_FILE "ecclistFile" #define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
#define RILCONF_ALLOW_DATA_REQ "allowDataReq" #define RILCONF_VENDOR_DRIVER "vendorDriver"
#define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery" #define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat" #define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay"
#define RILCONF_VENDOR_DRIVER "vendorDriver" #define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit" #define RILCONF_REMOTE_HANGUP_REASONS "remoteHangupReasons"
#define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay" #define RILCONF_DEFAULT_LEGACY_IMEI_QUERY "legacyImeiQuery"
#define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
#define RILCONF_REMOTE_HANGUP_REASONS "remoteHangupReasons"
#define RILCONF_LEGACY_IMEI_QUERY "legacyImeiQuery"
#define RILCONF_RADIO_POWER_CYCLE "radioPowerCycle"
#define RILCONF_CONFIRM_RADIO_POWER_ON "confirmRadioPowerOn"
#define RILCONF_SINGLE_DATA_CONTEXT "singleDataContext"
/* Modem error ids */ /* Modem error ids */
#define RIL_ERROR_ID_RILD_RESTART "rild-restart" #define RIL_ERROR_ID_RILD_RESTART "rild-restart"
#define RIL_ERROR_ID_CAPS_SWITCH_ABORTED "ril-caps-switch-aborted" #define RIL_ERROR_ID_CAPS_SWITCH_ABORTED "ril-caps-switch-aborted"
enum ril_plugin_io_events { enum ril_plugin_io_events {
IO_EVENT_CONNECTED, IO_EVENT_CONNECTED,
@@ -194,8 +174,8 @@ typedef struct sailfish_slot_impl {
char *imei; char *imei;
char *imeisv; char *imeisv;
char *name; char *name;
char *transport_name; char *sockpath;
GHashTable *transport_params; char *sub;
char *ecclist_file; char *ecclist_file;
int timeout; /* RIL timeout, in milliseconds */ int timeout; /* RIL timeout, in milliseconds */
int index; int index;
@@ -213,7 +193,6 @@ typedef struct sailfish_slot_impl {
struct ril_vendor_hook *vendor_hook; struct ril_vendor_hook *vendor_hook;
struct ril_data *data; struct ril_data *data;
gboolean legacy_imei_query; gboolean legacy_imei_query;
enum sailfish_slot_flags slot_flags;
guint start_timeout; guint start_timeout;
guint start_timeout_id; guint start_timeout_id;
MceDisplay *display; MceDisplay *display;
@@ -985,12 +964,10 @@ static void ril_plugin_slot_connected(ril_slot *slot)
slot->radio = ril_radio_new(slot->io); slot->radio = ril_radio_new(slot->io);
GASSERT(!slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED]); GASSERT(!slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED]);
if (slot->config.confirm_radio_power_on) { slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED] =
slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED] = grilio_channel_add_unsol_event_handler(slot->io,
grilio_channel_add_unsol_event_handler(slot->io,
ril_plugin_radio_state_changed, ril_plugin_radio_state_changed,
RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, slot); RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, slot);
}
GASSERT(!slot->sim_card); GASSERT(!slot->sim_card);
slot->sim_card = ril_sim_card_new(slot->io, slot->config.slot, slot->sim_card = ril_sim_card_new(slot->io, slot->config.slot,
@@ -1004,8 +981,7 @@ static void ril_plugin_slot_connected(ril_slot *slot)
GASSERT(!slot->network); GASSERT(!slot->network);
slot->network = ril_network_new(slot->path, slot->io, log_prefix, slot->network = ril_network_new(slot->path, slot->io, log_prefix,
slot->radio, slot->sim_card, slot->sim_settings, slot->radio, slot->sim_card, slot->sim_settings);
&slot->config);
GASSERT(!slot->vendor_hook); GASSERT(!slot->vendor_hook);
slot->vendor_hook = ril_vendor_create_hook(slot->vendor, slot->io, slot->vendor_hook = ril_vendor_create_hook(slot->vendor, slot->io,
@@ -1042,10 +1018,9 @@ static void ril_plugin_slot_connected(ril_slot *slot)
slot->start_timeout_id = 0; slot->start_timeout_id = 0;
/* Register this slot with the sailfish manager plugin */ /* Register this slot with the sailfish manager plugin */
slot->handle = sailfish_manager_slot_add2(plugin->handle, slot, slot->handle = sailfish_manager_slot_add(plugin->handle, slot,
slot->path, slot->config.techs, slot->imei, slot->path, slot->config.techs, slot->imei,
slot->imeisv, ril_plugin_sim_state(slot), slot->imeisv, ril_plugin_sim_state(slot));
slot->slot_flags);
sailfish_manager_set_cell_info(slot->handle, slot->cell_info); sailfish_manager_set_cell_info(slot->handle, slot->cell_info);
/* Check if this was the last slot we were waiting for */ /* Check if this was the last slot we were waiting for */
@@ -1068,8 +1043,8 @@ static void ril_plugin_slot_connected_cb(GRilIoChannel *io, void *user_data)
static void ril_plugin_init_io(ril_slot *slot) static void ril_plugin_init_io(ril_slot *slot)
{ {
if (!slot->io) { if (!slot->io) {
slot->io = grilio_channel_new(ofono_ril_transport_connect DBG("%s %s", slot->sockpath, slot->sub);
(slot->transport_name, slot->transport_params)); slot->io = grilio_channel_new_socket(slot->sockpath, slot->sub);
if (slot->io) { if (slot->io) {
ril_debug_trace_update(slot); ril_debug_trace_update(slot);
ril_debug_dump_update(slot); ril_debug_dump_update(slot);
@@ -1125,7 +1100,7 @@ static void ril_plugin_retry_init_io(ril_slot *slot)
g_source_remove(slot->retry_id); g_source_remove(slot->retry_id);
} }
DBG("%s", slot->path); DBG("%s %s", slot->sockpath, slot->sub);
slot->retry_id = g_timeout_add_seconds(RIL_RETRY_SECS, slot->retry_id = g_timeout_add_seconds(RIL_RETRY_SECS,
ril_plugin_retry_init_io_cb, slot); ril_plugin_retry_init_io_cb, slot);
} }
@@ -1153,7 +1128,7 @@ static void ril_slot_free(ril_slot *slot)
{ {
ril_plugin* plugin = slot->plugin; ril_plugin* plugin = slot->plugin;
DBG("%s", slot->path); DBG("%s", slot->sockpath);
ril_plugin_shutdown_slot(slot, TRUE); ril_plugin_shutdown_slot(slot, TRUE);
plugin->slots = g_slist_remove(plugin->slots, slot); plugin->slots = g_slist_remove(plugin->slots, slot);
mce_display_remove_all_handlers(slot->display, slot->display_event_id); mce_display_remove_all_handlers(slot->display, slot->display_event_id);
@@ -1167,8 +1142,8 @@ static void ril_slot_free(ril_slot *slot)
g_free(slot->imei); g_free(slot->imei);
g_free(slot->imeisv); g_free(slot->imeisv);
g_free(slot->name); g_free(slot->name);
g_free(slot->transport_name); g_free(slot->sockpath);
g_hash_table_destroy(slot->transport_params); g_free(slot->sub);
g_free(slot->ecclist_file); g_free(slot->ecclist_file);
g_free(slot); g_free(slot);
} }
@@ -1178,7 +1153,7 @@ static gboolean ril_plugin_slot_start_timeout(gpointer user_data)
ril_slot *slot = user_data; ril_slot *slot = user_data;
ril_plugin* plugin = slot->plugin; ril_plugin* plugin = slot->plugin;
DBG("%s", slot->path); DBG("%s", slot->sockpath);
plugin->slots = g_slist_remove(plugin->slots, slot); plugin->slots = g_slist_remove(plugin->slots, slot);
slot->start_timeout_id = 0; slot->start_timeout_id = 0;
ril_slot_free(slot); ril_slot_free(slot);
@@ -1186,31 +1161,24 @@ static gboolean ril_plugin_slot_start_timeout(gpointer user_data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static ril_slot *ril_plugin_slot_new_take(char *transport, static ril_slot *ril_plugin_slot_new_take(char *sockpath, char *path,
GHashTable *transport_params, char *dbus_path, char *name, guint slot_index)
char *name, guint slot_index)
{ {
ril_slot *slot = g_new0(ril_slot, 1); ril_slot *slot = g_new0(ril_slot, 1);
struct ril_slot_config *config = &slot->config; struct ril_slot_config *config = &slot->config;
slot->transport_name = transport; slot->sockpath = sockpath;
slot->transport_params = transport_params; slot->path = path;
slot->path = dbus_path;
slot->name = name; slot->name = name;
config->slot = slot_index; config->slot = slot_index;
config->techs = RILMODEM_DEFAULT_TECHS; config->techs = RILMODEM_DEFAULT_TECHS;
config->lte_network_mode = RILMODEM_DEFAULT_LTE_MODE;
config->empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY; config->empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
config->radio_power_cycle = RILMODEM_DEFAULT_RADIO_POWER_CYCLE;
config->confirm_radio_power_on =
RILMODEM_DEFAULT_CONFIRM_RADIO_POWER_ON;
config->enable_voicecall = RILMODEM_DEFAULT_ENABLE_VOICECALL; config->enable_voicecall = RILMODEM_DEFAULT_ENABLE_VOICECALL;
config->enable_cbs = RILMODEM_DEFAULT_ENABLE_CBS; config->enable_cbs = RILMODEM_DEFAULT_ENABLE_CBS;
config->query_available_band_mode = config->query_available_band_mode =
RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE; RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT; slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS; slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->slot_flags = RILMODEM_DEFAULT_SLOT_FLAGS;
slot->legacy_imei_query = RILMODEM_DEFAULT_LEGACY_IMEI_QUERY; slot->legacy_imei_query = RILMODEM_DEFAULT_LEGACY_IMEI_QUERY;
slot->start_timeout = RILMODEM_DEFAULT_START_TIMEOUT; slot->start_timeout = RILMODEM_DEFAULT_START_TIMEOUT;
slot->data_opt.allow_data = RILMODEM_DEFAULT_DATA_OPT; slot->data_opt.allow_data = RILMODEM_DEFAULT_DATA_OPT;
@@ -1229,7 +1197,7 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
mce_display_add_state_changed_handler(slot->display, mce_display_add_state_changed_handler(slot->display,
ril_plugin_display_cb, slot); ril_plugin_display_cb, slot);
slot->watch = sailfish_watch_new(dbus_path); slot->watch = sailfish_watch_new(path);
slot->watch_event_id[WATCH_EVENT_MODEM] = slot->watch_event_id[WATCH_EVENT_MODEM] =
sailfish_watch_add_modem_changed_handler(slot->watch, sailfish_watch_add_modem_changed_handler(slot->watch,
ril_plugin_slot_modem_changed, slot); ril_plugin_slot_modem_changed, slot);
@@ -1259,23 +1227,11 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
} }
} }
static ril_slot *ril_plugin_slot_new_socket(const char *sockpath, static ril_slot *ril_plugin_slot_new(const char *sockpath, const char *path,
const char *sub, const char *dbus_path,
const char *name, guint slot_index) const char *name, guint slot_index)
{ {
/* RIL socket configuration */ return ril_plugin_slot_new_take(g_strdup(sockpath), g_strdup(path),
GHashTable *params = g_hash_table_new_full(g_str_hash, g_str_equal, g_strdup(name), slot_index);
g_free, g_free);
g_hash_table_insert(params, g_strdup(RIL_TRANSPORT_SOCKET_PATH),
g_strdup(sockpath));
if (sub) {
g_hash_table_insert(params, g_strdup(RIL_TRANSPORT_SOCKET_SUB),
g_strdup(sub));
}
return ril_plugin_slot_new_take(g_strdup(RIL_TRANSPORT_SOCKET), params,
g_strdup(dbus_path), g_strdup(name), slot_index);
} }
static GSList *ril_plugin_create_default_config() static GSList *ril_plugin_create_default_config()
@@ -1284,135 +1240,55 @@ static GSList *ril_plugin_create_default_config()
if (g_file_test(RILMODEM_DEFAULT_SOCK2, G_FILE_TEST_EXISTS)) { if (g_file_test(RILMODEM_DEFAULT_SOCK2, G_FILE_TEST_EXISTS)) {
DBG("Falling back to default dual SIM config"); DBG("Falling back to default dual SIM config");
list = g_slist_append(list, ril_plugin_slot_new_socket list = g_slist_append(list,
(RILMODEM_DEFAULT_SOCK, NULL, ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK,
RILCONF_PATH_PREFIX "0", "RIL1", 0)); RILCONF_PATH_PREFIX "0", "RIL1", 0));
list = g_slist_append(list, ril_plugin_slot_new_socket list = g_slist_append(list,
(RILMODEM_DEFAULT_SOCK2, NULL, ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK2,
RILCONF_PATH_PREFIX "1", "RIL2", 1)); RILCONF_PATH_PREFIX "1", "RIL2", 1));
} else { } else {
ril_slot *slot = ril_plugin_slot_new(RILMODEM_DEFAULT_SOCK,
RILCONF_PATH_PREFIX "0", "RIL", 0);
DBG("Falling back to default single SIM config"); DBG("Falling back to default single SIM config");
list = g_slist_append(list, ril_plugin_slot_new_socket slot->sub = g_strdup(RILMODEM_DEFAULT_SUB);
(RILMODEM_DEFAULT_SOCK, RILMODEM_DEFAULT_SUB, list = g_slist_append(list, slot);
RILCONF_PATH_PREFIX "0", "RIL", 0));
} }
return list; return list;
} }
/*
* Parse the spec according to the following grammar:
*
* spec: transport | transport ':' parameters
* params: param | params ';' param
* param: name '=' value
* transport: STRING
* name: STRING
* value: STRING
*
* For example, a RIL socket spec may look like this:
*
* socket:path=/dev/socket/rild;sub=SUB1
*/
static char *ril_plugin_parse_transport_spec(const char *spec,
GHashTable *params)
{
char *transport = NULL;
char *sep = strchr(spec, ':');
if (sep) {
transport = g_strstrip(g_strndup(spec, sep - spec));
if (transport[0]) {
char **list = g_strsplit(sep + 1, ";", 0);
char **ptr;
for (ptr = list; *ptr; ptr++) {
const char *p = *ptr;
sep = strchr(p, '=');
if (sep) {
char *name = g_strndup(p, sep - p);
char* value = g_strdup(sep + 1);
g_hash_table_insert(params,
g_strstrip(name),
g_strstrip(value));
}
}
g_strfreev(list);
return transport;
}
} else {
/* Use default transport attributes */
transport = g_strstrip(g_strdup(spec));
if (transport[0]) {
return transport;
}
}
g_free(transport);
return NULL;
}
static ril_slot *ril_plugin_parse_config_group(GKeyFile *file, static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
const char *group) const char *group)
{ {
ril_slot *slot; ril_slot *slot;
struct ril_slot_config *config; struct ril_slot_config *config;
gboolean bval;
int ival; int ival;
char *sval; char *sval;
char **strv; char **strv;
GHashTable *transport_params = g_hash_table_new_full(g_str_hash, char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
g_str_equal, g_free, g_free);
char *transport = NULL;
char *transport_spec = g_key_file_get_string(file, group,
RILCONF_TRANSPORT, NULL);
if (transport_spec) { if (!sock) {
transport = ril_plugin_parse_transport_spec(transport_spec, ofono_warn("no socket path for %s", group);
transport_params);
if (transport) {
DBG("%s: %s:%s", group, transport,
strchr(transport_spec, ':') + 1);
}
g_free(transport_spec);
} else {
/* Fall back to socket transport */
char *sockpath = g_key_file_get_string(file, group,
RILCONF_SOCKET, NULL);
if (sockpath) {
char *sub = g_key_file_get_string(file, group,
RILCONF_SUB, NULL);
transport = g_strdup(RIL_TRANSPORT_SOCKET);
g_hash_table_insert(transport_params,
g_strdup(RIL_TRANSPORT_SOCKET_PATH),
sockpath);
if (sub && strlen(sub) == RIL_SUB_SIZE) {
DBG("%s: %s:%s", group, sockpath, sub);
g_hash_table_insert(transport_params,
g_strdup(RIL_TRANSPORT_SOCKET_SUB),
sub);
} else {
DBG("%s: %s", group, sockpath);
g_free(sub);
}
}
}
if (!transport) {
ofono_warn("No usable RIL transport defined for %s", group);
g_hash_table_destroy(transport_params);
return NULL; return NULL;
} }
slot = ril_plugin_slot_new_take(transport, transport_params, slot = ril_plugin_slot_new_take(sock,
g_strconcat("/", group, NULL), g_strconcat("/", group, NULL),
ril_config_get_string(file, group, RILCONF_NAME), ril_config_get_string(file, group, RILCONF_NAME),
RILMODEM_DEFAULT_SLOT); RILMODEM_DEFAULT_SLOT);
config = &slot->config; config = &slot->config;
/* sub */
sval = ril_config_get_string(file, group, RILCONF_SUB);
if (sval && strlen(sval) == RIL_SUB_SIZE) {
DBG("%s: %s:%s", group, sock, sval);
slot->sub = sval;
} else {
DBG("%s: %s", group, sock);
g_free(sval);
}
/* slot */ /* slot */
if (ril_config_get_integer(file, group, RILCONF_SLOT, &ival) && if (ril_config_get_integer(file, group, RILCONF_SLOT, &ival) &&
ival >= 0) { ival >= 0) {
@@ -1501,20 +1377,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
} }
g_strfreev(strv); g_strfreev(strv);
} }
/* lteNetworkMode */
if (ril_config_get_integer(file, group, RILCONF_LTE_MODE,
&config->lte_network_mode)) {
DBG("%s: " RILCONF_LTE_MODE " %d", group,
config->lte_network_mode);
}
/* networkModeTimeout */
if (ril_config_get_integer(file, group, RILCONF_NETWORK_MODE_TIMEOUT,
&config->network_mode_timeout)) {
DBG("%s: " RILCONF_NETWORK_MODE_TIMEOUT " %d", group,
config->network_mode_timeout);
}
/* enable4G (deprecated but still supported) */ /* enable4G (deprecated but still supported) */
ival = config->techs; ival = config->techs;
@@ -1532,28 +1394,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->empty_pin_query ? "on" : "off"); config->empty_pin_query ? "on" : "off");
} }
/* radioPowerCycle */
if (ril_config_get_boolean(file, group, RILCONF_RADIO_POWER_CYCLE,
&config->radio_power_cycle)) {
DBG("%s: " RILCONF_RADIO_POWER_CYCLE " %s", group,
config->radio_power_cycle ? "on" : "off");
}
/* confirmRadioPowerOn */
if (ril_config_get_boolean(file, group, RILCONF_CONFIRM_RADIO_POWER_ON,
&config->confirm_radio_power_on)) {
DBG("%s: " RILCONF_CONFIRM_RADIO_POWER_ON " %s", group,
config->confirm_radio_power_on ? "on" : "off");
}
/* singleDataContext */
if (ril_config_get_boolean(file, group, RILCONF_SINGLE_DATA_CONTEXT,
&bval) && bval) {
DBG("%s: " RILCONF_SINGLE_DATA_CONTEXT " %s", group,
bval ? "on" : "off");
slot->slot_flags |= SAILFISH_SLOT_SINGLE_CONTEXT;
}
/* uiccWorkaround */ /* uiccWorkaround */
if (ril_config_get_flag(file, group, RILCONF_UICC_WORKAROUND, if (ril_config_get_flag(file, group, RILCONF_UICC_WORKAROUND,
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND, RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
@@ -1634,9 +1474,10 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
} }
/* legacyImeiQuery */ /* legacyImeiQuery */
if (ril_config_get_boolean(file, group, RILCONF_LEGACY_IMEI_QUERY, if (ril_config_get_boolean(file, group,
RILCONF_DEFAULT_LEGACY_IMEI_QUERY,
&slot->legacy_imei_query)) { &slot->legacy_imei_query)) {
DBG("%s: " RILCONF_LEGACY_IMEI_QUERY " %s", group, DBG("%s: " RILCONF_DEFAULT_LEGACY_IMEI_QUERY " %s", group,
slot->legacy_imei_query ? "on" : "off"); slot->legacy_imei_query ? "on" : "off");
} }
@@ -1714,7 +1555,7 @@ static void ril_plugin_parse_identity(struct ril_plugin_identity *identity,
int n; int n;
/* Try numeric */ /* Try numeric */
if (gutil_parse_int(group, 0, &n)) { if (ril_parse_int(group, 0, &n)) {
gr = getgrgid(n); gr = getgrgid(n);
} }
} }
@@ -1726,7 +1567,7 @@ static void ril_plugin_parse_identity(struct ril_plugin_identity *identity,
int n; int n;
/* Try numeric */ /* Try numeric */
if (gutil_parse_int(user, 0, &n)) { if (ril_parse_int(user, 0, &n)) {
pw = getpwuid(n); pw = getpwuid(n);
} }
} }
@@ -1757,7 +1598,7 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
const char *group = groups[i]; const char *group = groups[i];
if (g_str_has_prefix(group, RILCONF_MODEM_PREFIX)) { if (g_str_has_prefix(group, RILCONF_DEV_PREFIX)) {
/* Modem configuration */ /* Modem configuration */
ril_slot *slot = ril_plugin_parse_config_group(file, ril_slot *slot = ril_plugin_parse_config_group(file,
group); group);
@@ -2081,31 +1922,10 @@ static void ril_slot_enabled_changed(struct sailfish_slot_impl *s)
} }
} }
/**
* RIL socket transport factory
*/
static struct grilio_transport *ril_socket_transport_connect(GHashTable *args)
{
const char* path = g_hash_table_lookup(args, RIL_TRANSPORT_SOCKET_PATH);
const char* sub = g_hash_table_lookup(args, RIL_TRANSPORT_SOCKET_SUB);
GASSERT(path);
if (path) {
DBG("%s %s", path, sub);
return grilio_transport_socket_new_path(path, sub);
}
return NULL;
}
/* Global part (that requires access to global variables) */ /* Global part (that requires access to global variables) */
static struct sailfish_slot_driver_reg *ril_driver = NULL; static struct sailfish_slot_driver_reg *ril_driver = NULL;
static guint ril_driver_init_id = 0; static guint ril_driver_init_id = 0;
static const struct ofono_ril_transport ril_socket_transport = {
.name = RIL_TRANSPORT_SOCKET,
.api_version = OFONO_RIL_TRANSPORT_API_VERSION,
.connect = ril_socket_transport_connect
};
static void ril_debug_trace_notify(struct ofono_debug_desc *desc) static void ril_debug_trace_notify(struct ofono_debug_desc *desc)
{ {
@@ -2151,9 +1971,6 @@ static gboolean ril_plugin_start(gpointer user_data)
DBG(""); DBG("");
ril_driver_init_id = 0; ril_driver_init_id = 0;
/* Socket transport can be registered right away */
ofono_ril_transport_register(&ril_socket_transport);
/* Register the driver */ /* Register the driver */
ril_driver = sailfish_slot_driver_register(&ril_slot_driver); ril_driver = sailfish_slot_driver_register(&ril_slot_driver);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
@@ -2189,7 +2006,6 @@ static void ril_plugin_exit(void)
DBG(""); DBG("");
GASSERT(ril_driver); GASSERT(ril_driver);
ofono_ril_transport_unregister(&ril_socket_transport);
ofono_modem_driver_unregister(&ril_modem_driver); ofono_modem_driver_unregister(&ril_modem_driver);
ofono_sim_driver_unregister(&ril_sim_driver); ofono_sim_driver_unregister(&ril_sim_driver);
ofono_sms_driver_unregister(&ril_sms_driver); ofono_sms_driver_unregister(&ril_sms_driver);

View File

@@ -71,16 +71,14 @@ G_DEFINE_TYPE(RilRadio, ril_radio, G_TYPE_OBJECT)
#define RIL_RADIO_TYPE (ril_radio_get_type()) #define RIL_RADIO_TYPE (ril_radio_get_type())
#define RIL_RADIO(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_RADIO_TYPE,RilRadio)) #define RIL_RADIO(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_RADIO_TYPE,RilRadio))
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->priv->log_prefix, ##args)
static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on); static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on);
static inline gboolean ril_radio_power_should_be_on(struct ril_radio *self) static inline gboolean ril_radio_power_should_be_on(struct ril_radio *self)
{ {
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
return (self->online || g_hash_table_size(priv->req_table) > 0) && return self->online && !priv->power_cycle &&
!priv->power_cycle; g_hash_table_size(priv->req_table) > 0;
} }
static inline gboolean ril_radio_state_off(enum ril_radio_state radio_state) static inline gboolean ril_radio_state_off(enum ril_radio_state radio_state)
@@ -104,7 +102,7 @@ static gboolean ril_radio_power_request_retry_cb(gpointer user_data)
struct ril_radio *self = RIL_RADIO(user_data); struct ril_radio *self = RIL_RADIO(user_data);
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
DBG_(self, ""); DBG("%s", priv->log_prefix);
GASSERT(priv->retry_id); GASSERT(priv->retry_id);
priv->retry_id = 0; priv->retry_id = 0;
ril_radio_submit_power_request(self, ril_radio_submit_power_request(self,
@@ -118,7 +116,7 @@ static void ril_radio_cancel_retry(struct ril_radio *self)
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
if (priv->retry_id) { if (priv->retry_id) {
DBG_(self, "retry cancelled"); DBG("%sretry cancelled", priv->log_prefix);
g_source_remove(priv->retry_id); g_source_remove(priv->retry_id);
priv->retry_id = 0; priv->retry_id = 0;
} }
@@ -131,8 +129,8 @@ static void ril_radio_check_state(struct ril_radio *self)
if (!priv->pending_id) { if (!priv->pending_id) {
gboolean should_be_on = ril_radio_power_should_be_on(self); gboolean should_be_on = ril_radio_power_should_be_on(self);
if (ril_radio_state_on(priv->last_known_state) == if (ril_radio_state_on(self->priv->last_known_state) ==
should_be_on) { should_be_on) {
/* All is good, cancel pending retry if there is one */ /* All is good, cancel pending retry if there is one */
ril_radio_cancel_retry(self); ril_radio_cancel_retry(self);
} else if (priv->state_changed_while_request_pending) { } else if (priv->state_changed_while_request_pending) {
@@ -140,7 +138,7 @@ static void ril_radio_check_state(struct ril_radio *self)
ril_radio_submit_power_request(self, should_be_on); ril_radio_submit_power_request(self, should_be_on);
} else if (!priv->retry_id) { } else if (!priv->retry_id) {
/* There has been no reaction so far, wait a bit */ /* There has been no reaction so far, wait a bit */
DBG_(self, "retry scheduled"); DBG("%sretry scheduled", priv->log_prefix);
priv->retry_id = g_timeout_add_seconds(POWER_RETRY_SECS, priv->retry_id = g_timeout_add_seconds(POWER_RETRY_SECS,
ril_radio_power_request_retry_cb, self); ril_radio_power_request_retry_cb, self);
} }
@@ -149,38 +147,33 @@ static void ril_radio_check_state(struct ril_radio *self)
/* Don't update public state while something is pending */ /* Don't update public state while something is pending */
if (!priv->pending_id && !priv->retry_id && if (!priv->pending_id && !priv->retry_id &&
self->state != priv->last_known_state) { self->state != priv->last_known_state) {
DBG_(self, "%s -> %s", ril_radio_state_to_string(self->state), DBG("%s%s -> %s", priv->log_prefix,
ril_radio_state_to_string(self->state),
ril_radio_state_to_string(priv->last_known_state)); ril_radio_state_to_string(priv->last_known_state));
self->state = priv->last_known_state; self->state = priv->last_known_state;
ril_radio_emit_signal(self, SIGNAL_STATE_CHANGED); ril_radio_emit_signal(self, SIGNAL_STATE_CHANGED);
} }
} }
static void ril_radio_power_request_done(struct ril_radio *self)
{
struct ril_radio_priv *priv = self->priv;
GASSERT(priv->pending_id);
priv->pending_id = 0;
if (priv->next_state_valid) {
ril_radio_submit_power_request(self, priv->next_state);
} else {
ril_radio_check_state(self);
}
}
static void ril_radio_power_request_cb(GRilIoChannel *channel, int ril_status, static void ril_radio_power_request_cb(GRilIoChannel *channel, int ril_status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_radio *self = RIL_RADIO(user_data); struct ril_radio *self = RIL_RADIO(user_data);
struct ril_radio_priv *priv = self->priv;
GASSERT(priv->pending_id);
priv->pending_id = 0;
if (ril_status != RIL_E_SUCCESS) { if (ril_status != RIL_E_SUCCESS) {
ofono_error("Power request failed: %s", ofono_error("Power request failed: %s",
ril_error_to_string(ril_status)); ril_error_to_string(ril_status));
} }
ril_radio_power_request_done(self); if (priv->next_state_valid) {
ril_radio_submit_power_request(self, priv->next_state);
} else {
ril_radio_check_state(self);
}
} }
static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on) static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on)
@@ -221,18 +214,13 @@ static void ril_radio_power_request(struct ril_radio *self, gboolean on,
/* Wait for the pending request to complete */ /* Wait for the pending request to complete */
priv->next_state_valid = TRUE; priv->next_state_valid = TRUE;
priv->next_state = on; priv->next_state = on;
DBG_(self, "%s (queued)", on_off); DBG("%s%s (queued)", priv->log_prefix, on_off);
} else { } else {
DBG_(self, "%s (ignored)", on_off); DBG("%s%s (ignored)", priv->log_prefix, on_off);
} }
} else { } else {
if (ril_radio_state_on(priv->last_known_state) == on) { DBG("%s%s", priv->log_prefix, on_off);
DBG_(self, "%s (already)", on_off); ril_radio_submit_power_request(self, on);
ril_radio_check_state(self);
} else {
DBG_(self, "%s", on_off);
ril_radio_submit_power_request(self, on);
}
} }
} }
@@ -249,12 +237,12 @@ void ril_radio_power_cycle(struct ril_radio *self)
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
if (ril_radio_state_off(priv->last_known_state)) { if (ril_radio_state_off(priv->last_known_state)) {
DBG_(self, "power is already off"); DBG("%spower is already off", priv->log_prefix);
GASSERT(!priv->power_cycle); GASSERT(!priv->power_cycle);
} else if (priv->power_cycle) { } else if (priv->power_cycle) {
DBG_(self, "already in progress"); DBG("%salready in progress", priv->log_prefix);
} else { } else {
DBG_(self, "initiated"); DBG("%sinitiated", priv->log_prefix);
priv->power_cycle = TRUE; priv->power_cycle = TRUE;
if (!priv->pending_id) { if (!priv->pending_id) {
ril_radio_submit_power_request(self, FALSE); ril_radio_submit_power_request(self, FALSE);
@@ -271,7 +259,7 @@ void ril_radio_power_on(struct ril_radio *self, gpointer tag)
if (!g_hash_table_contains(priv->req_table, tag)) { if (!g_hash_table_contains(priv->req_table, tag)) {
gboolean was_on = ril_radio_power_should_be_on(self); gboolean was_on = ril_radio_power_should_be_on(self);
DBG_(self, "%p", tag); DBG("%s%p", priv->log_prefix, tag);
g_hash_table_insert(priv->req_table, tag, tag); g_hash_table_insert(priv->req_table, tag, tag);
if (!was_on && ril_radio_power_should_be_on(self)) { if (!was_on && ril_radio_power_should_be_on(self)) {
ril_radio_power_request(self, TRUE, FALSE); ril_radio_power_request(self, TRUE, FALSE);
@@ -286,7 +274,7 @@ void ril_radio_power_off(struct ril_radio *self, gpointer tag)
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
if (g_hash_table_remove(priv->req_table, tag)) { if (g_hash_table_remove(priv->req_table, tag)) {
DBG_(self, "%p", tag); DBG("%s%p", priv->log_prefix, tag);
if (!ril_radio_power_should_be_on(self)) { if (!ril_radio_power_should_be_on(self)) {
/* The last one turns the lights off */ /* The last one turns the lights off */
ril_radio_power_request(self, FALSE, FALSE); ril_radio_power_request(self, FALSE, FALSE);
@@ -358,41 +346,20 @@ static void ril_radio_state_changed(GRilIoChannel *io, guint code,
if (radio_state != RADIO_STATE_UNAVAILABLE) { if (radio_state != RADIO_STATE_UNAVAILABLE) {
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
DBG_(self, "%s", ril_radio_state_to_string(radio_state)); DBG("%s%s", priv->log_prefix,
ril_radio_state_to_string(radio_state));
GASSERT(!priv->pending_id || !priv->retry_id); GASSERT(!priv->pending_id || !priv->retry_id);
if (priv->power_cycle && ril_radio_state_off(radio_state)) { if (priv->power_cycle && ril_radio_state_off(radio_state)) {
DBG_(self, "switched off for power cycle"); DBG("%sswitched off for power cycle", priv->log_prefix);
priv->power_cycle = FALSE; priv->power_cycle = FALSE;
} }
priv->last_known_state = radio_state;
if (priv->pending_id) { if (priv->pending_id) {
if (ril_radio_state_on(radio_state) == priv->state_changed_while_request_pending++;
ril_radio_power_should_be_on(self)) {
DBG_(self, "dropping pending request");
/*
* All right, the modem has switched to the
* desired state, drop the request.
*/
grilio_queue_cancel_request(priv->q,
priv->pending_id, FALSE);
/*
* This will zero pending_id and call
* ril_radio_check_state() if necesary:
*/
ril_radio_power_request_done(self);
/* We are done */
return;
} else {
/* Something weird is going on */
priv->state_changed_while_request_pending++;
}
} }
priv->last_known_state = radio_state;
ril_radio_check_state(self); ril_radio_check_state(self);
} }
} }
@@ -407,7 +374,7 @@ struct ril_radio *ril_radio_new(GRilIoChannel *io)
priv->log_prefix = priv->log_prefix =
(io && io->name && io->name[0] && strcmp(io->name, "RIL")) ? (io && io->name && io->name[0] && strcmp(io->name, "RIL")) ?
g_strconcat(io->name, " ", NULL) : g_strdup(""); g_strconcat(io->name, " ", NULL) : g_strdup("");
DBG_(self, ""); DBG("%s", priv->log_prefix);
priv->state_event_id = grilio_channel_add_unsol_event_handler(priv->io, priv->state_event_id = grilio_channel_add_unsol_event_handler(priv->io,
ril_radio_state_changed, ril_radio_state_changed,
RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, self); RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, self);
@@ -464,7 +431,7 @@ static void ril_radio_finalize(GObject *object)
struct ril_radio *self = RIL_RADIO(object); struct ril_radio *self = RIL_RADIO(object);
struct ril_radio_priv *priv = self->priv; struct ril_radio_priv *priv = self->priv;
DBG_(self, ""); DBG("%s", priv->log_prefix);
g_free(priv->log_prefix); g_free(priv->log_prefix);
grilio_channel_unref(priv->io); grilio_channel_unref(priv->io);
grilio_queue_unref(priv->q); grilio_queue_unref(priv->q);

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2017-2018 Jolla Ltd. * Copyright (C) 2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -71,7 +71,6 @@ struct ril_radio_caps {
gulong max_pref_mode_event_id; gulong max_pref_mode_event_id;
gulong radio_event_id; gulong radio_event_id;
int tx_id; int tx_id;
int tx_pending;
struct ril_data *data; struct ril_data *data;
struct ril_radio *radio; struct ril_radio *radio;
struct ril_network *network; struct ril_network *network;
@@ -86,6 +85,7 @@ typedef struct ril_radio_caps_manager {
GObject object; GObject object;
GPtrArray *caps_list; GPtrArray *caps_list;
guint check_id; guint check_id;
int tx_pending;
int tx_id; int tx_id;
int tx_phase_index; int tx_phase_index;
gboolean tx_failed; gboolean tx_failed;
@@ -453,7 +453,7 @@ struct ril_radio_caps *ril_radio_caps_new(struct ril_radio_caps_manager *mgr,
struct ril_radio_caps *self = struct ril_radio_caps *self =
g_slice_new0(struct ril_radio_caps); g_slice_new0(struct ril_radio_caps);
g_atomic_int_set(&self->ref_count, 1); self->ref_count = 1;
self->slot = config->slot; self->slot = config->slot;
self->log_prefix = (log_prefix && log_prefix[0]) ? self->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup(""); g_strconcat(log_prefix, " ", NULL) : g_strdup("");
@@ -471,16 +471,13 @@ struct ril_radio_caps *ril_radio_caps_new(struct ril_radio_caps_manager *mgr,
self->simcard_event_id[SIM_EVENT_STATE_CHANGED] = self->simcard_event_id[SIM_EVENT_STATE_CHANGED] =
ril_sim_card_add_state_changed_handler(sim, ril_sim_card_add_state_changed_handler(sim,
ril_radio_caps_simcard_event, self); ril_radio_caps_simcard_event, self);
self->simcard_event_id[SIM_EVENT_IO_ACTIVE_CHANGED] =
ril_sim_card_add_sim_io_active_changed_handler(sim,
ril_radio_caps_simcard_event, self);
self->network = ril_network_ref(net); self->network = ril_network_ref(net);
self->settings_event_id[SETTINGS_EVENT_PREF_MODE] = self->settings_event_id[SETTINGS_EVENT_PREF_MODE] =
ril_sim_settings_add_pref_mode_changed_handler( ril_sim_settings_add_pref_mode_changed_handler(
settings, ril_radio_caps_settings_event, self); settings, ril_radio_caps_settings_event, self);
self->settings_event_id[SETTINGS_EVENT_IMSI] = self->settings_event_id[SETTINGS_EVENT_IMSI] =
ril_sim_settings_add_imsi_changed_handler( ril_sim_settings_add_pref_mode_changed_handler(
settings, ril_radio_caps_settings_event, self); settings, ril_radio_caps_settings_event, self);
self->max_pref_mode_event_id = self->max_pref_mode_event_id =
@@ -563,24 +560,6 @@ static void ril_radio_caps_manager_foreach_tx
} }
} }
static gboolean ril_radio_caps_manager_tx_pending
(struct ril_radio_caps_manager *self)
{
guint i;
const GPtrArray *list = self->caps_list;
for (i = 0; i < list->len; i++) {
const struct ril_radio_caps *caps = list->pdata[i];
/* Ignore the modems not associated with this transaction */
if (caps->tx_id == self->tx_id && caps->tx_pending > 0) {
return TRUE;
}
}
return FALSE;
}
/** /**
* Checks that all radio caps have been initialized (i.e. all the initial * Checks that all radio caps have been initialized (i.e. all the initial
* GET_RADIO_CAPABILITY requests have completed) and there's no transaction * GET_RADIO_CAPABILITY requests have completed) and there's no transaction
@@ -589,7 +568,7 @@ static gboolean ril_radio_caps_manager_tx_pending
static gboolean ril_radio_caps_manager_can_check static gboolean ril_radio_caps_manager_can_check
(struct ril_radio_caps_manager *self) (struct ril_radio_caps_manager *self)
{ {
if (self->caps_list && !ril_radio_caps_manager_tx_pending(self)) { if (self->caps_list && !self->tx_pending) {
const GPtrArray *list = self->caps_list; const GPtrArray *list = self->caps_list;
const struct ril_radio_caps *prev_caps = NULL; const struct ril_radio_caps *prev_caps = NULL;
gboolean all_modes_equal = TRUE; gboolean all_modes_equal = TRUE;
@@ -774,10 +753,6 @@ static void ril_radio_caps_manager_issue_requests
phase->send_new_cap ? &caps->new_cap : phase->send_new_cap ? &caps->new_cap :
&caps->old_cap; &caps->old_cap;
/* Count it */
caps->tx_pending++;
DBG_(caps, "tx_pending=%d", caps->tx_pending);
/* Encode and send the request */ /* Encode and send the request */
grilio_request_append_int32(req, grilio_request_append_int32(req,
RIL_RADIO_CAPABILITY_VERSION); RIL_RADIO_CAPABILITY_VERSION);
@@ -791,6 +766,9 @@ static void ril_radio_caps_manager_issue_requests
RIL_REQUEST_SET_RADIO_CAPABILITY, RIL_REQUEST_SET_RADIO_CAPABILITY,
handler, NULL, caps); handler, NULL, caps);
grilio_request_unref(req); grilio_request_unref(req);
/* Count it */
self->tx_pending++;
} }
} }
} }
@@ -813,6 +791,7 @@ static void ril_radio_caps_manager_next_transaction
{ {
ril_radio_caps_manager_foreach(self, ril_radio_caps_manager_foreach(self,
ril_radio_caps_manager_next_transaction_cb); ril_radio_caps_manager_next_transaction_cb);
self->tx_pending = 0;
self->tx_failed = FALSE; self->tx_failed = FALSE;
self->tx_phase_index = -1; self->tx_phase_index = -1;
self->tx_id++; self->tx_id++;
@@ -850,10 +829,8 @@ static void ril_radio_caps_manager_abort_cb(GRilIoChannel *io,
struct ril_radio_caps *caps = user_data; struct ril_radio_caps *caps = user_data;
struct ril_radio_caps_manager *self = caps->mgr; struct ril_radio_caps_manager *self = caps->mgr;
GASSERT(caps->tx_pending > 0); GASSERT(self->tx_pending > 0);
caps->tx_pending--; if (!(--self->tx_pending)) {
DBG_(caps, "tx_pending=%d", caps->tx_pending);
if (!ril_radio_caps_manager_tx_pending(self)) {
DBG("transaction aborted"); DBG("transaction aborted");
ril_radio_caps_manager_transaction_done(self); ril_radio_caps_manager_transaction_done(self);
} }
@@ -898,7 +875,7 @@ static void ril_radio_caps_manager_next_phase_cb(GRilIoChannel *io,
struct ril_radio_caps_manager *self = caps->mgr; struct ril_radio_caps_manager *self = caps->mgr;
gboolean ok = FALSE; gboolean ok = FALSE;
GASSERT(caps->tx_pending > 0); GASSERT(self->tx_pending > 0);
if (ril_status == RIL_E_SUCCESS) { if (ril_status == RIL_E_SUCCESS) {
struct ril_radio_capability cap; struct ril_radio_capability cap;
if (ril_radio_caps_parse(caps->log_prefix, data, len, &cap) && if (ril_radio_caps_parse(caps->log_prefix, data, len, &cap) &&
@@ -915,9 +892,7 @@ static void ril_radio_caps_manager_next_phase_cb(GRilIoChannel *io,
} }
} }
caps->tx_pending--; if (!(--self->tx_pending)) {
DBG_(caps, "tx_pending=%d", caps->tx_pending);
if (!ril_radio_caps_manager_tx_pending(self)) {
if (self->tx_failed) { if (self->tx_failed) {
ril_radio_caps_manager_abort_transaction(self); ril_radio_caps_manager_abort_transaction(self);
} else { } else {
@@ -932,7 +907,7 @@ static void ril_radio_caps_manager_next_phase
/* Note: -1 > 2 if 2 is unsigned (which turns -1 into 4294967295) */ /* Note: -1 > 2 if 2 is unsigned (which turns -1 into 4294967295) */
const int max_index = G_N_ELEMENTS(ril_radio_caps_tx_phase) - 1; const int max_index = G_N_ELEMENTS(ril_radio_caps_tx_phase) - 1;
GASSERT(!ril_radio_caps_manager_tx_pending(self)); GASSERT(!self->tx_pending);
if (self->tx_phase_index >= max_index) { if (self->tx_phase_index >= max_index) {
DBG("transaction %d is done", self->tx_id); DBG("transaction %d is done", self->tx_id);
ril_radio_caps_manager_transaction_done(self); ril_radio_caps_manager_transaction_done(self);
@@ -949,16 +924,14 @@ static void ril_radio_caps_manager_next_phase
static void ril_radio_caps_manager_data_off_done(GRilIoChannel *io, static void ril_radio_caps_manager_data_off_done(GRilIoChannel *io,
int status, const void *req_data, guint len, void *user_data) int status, const void *req_data, guint len, void *user_data)
{ {
struct ril_radio_caps *caps = user_data; struct ril_radio_caps_manager *self = RADIO_CAPS_MANAGER(user_data);
struct ril_radio_caps_manager *self = caps->mgr;
GASSERT(caps->tx_pending > 0); DBG("%d", self->tx_pending);
GASSERT(self->tx_pending > 0);
if (status != GRILIO_STATUS_OK) { if (status != GRILIO_STATUS_OK) {
self->tx_failed = TRUE; self->tx_failed = TRUE;
} }
caps->tx_pending--; if (!(--self->tx_pending)) {
DBG_(caps, "tx_pending=%d", caps->tx_pending);
if (!ril_radio_caps_manager_tx_pending(self)) {
if (self->tx_failed) { if (self->tx_failed) {
DBG("failed to start the transaction"); DBG("failed to start the transaction");
ril_data_manager_assert_data_on(self->data_manager); ril_data_manager_assert_data_on(self->data_manager);
@@ -978,13 +951,13 @@ static void ril_radio_caps_manager_data_off
{ {
GRilIoRequest *req = ril_request_allow_data_new(FALSE); GRilIoRequest *req = ril_request_allow_data_new(FALSE);
caps->tx_pending++; self->tx_pending++;
DBG_(caps, "tx_pending=%d", caps->tx_pending); DBG_(caps, "disallowing data");
grilio_request_set_timeout(req, DATA_OFF_TIMEOUT_MS); grilio_request_set_timeout(req, DATA_OFF_TIMEOUT_MS);
grilio_queue_send_request_full(caps->q, req, grilio_queue_send_request_full(caps->q, req,
RIL_REQUEST_ALLOW_DATA, RIL_REQUEST_ALLOW_DATA,
ril_radio_caps_manager_data_off_done, ril_radio_caps_manager_data_off_done,
NULL, caps); NULL, self);
grilio_request_unref(req); grilio_request_unref(req);
} }
@@ -994,16 +967,14 @@ static void ril_radio_caps_manager_deactivate_data_call_done(GRilIoChannel *io,
struct ril_radio_caps *caps = user_data; struct ril_radio_caps *caps = user_data;
struct ril_radio_caps_manager *self = caps->mgr; struct ril_radio_caps_manager *self = caps->mgr;
GASSERT(caps->tx_pending > 0); GASSERT(self->tx_pending > 0);
if (status != GRILIO_STATUS_OK) { if (status != GRILIO_STATUS_OK) {
self->tx_failed = TRUE; self->tx_failed = TRUE;
/* Something seems to be slightly broken, try requesting the /* Something seems to be slightly broken, try requesting the
* current state (later, after we release the transaction). */ * current state (later, after we release the transaction). */
ril_data_poll_call_state(caps->data); ril_data_poll_call_state(caps->data);
} }
caps->tx_pending--; if (!(--self->tx_pending)) {
DBG_(caps, "tx_pending=%d", caps->tx_pending);
if (!ril_radio_caps_manager_tx_pending(self)) {
if (self->tx_failed) { if (self->tx_failed) {
DBG("failed to start the transaction"); DBG("failed to start the transaction");
ril_radio_caps_manager_recheck_later(self); ril_radio_caps_manager_recheck_later(self);
@@ -1021,8 +992,8 @@ static void ril_radio_caps_deactivate_data_call(struct ril_radio_caps *caps,
{ {
GRilIoRequest *req = ril_request_deactivate_data_call_new(cid); GRilIoRequest *req = ril_request_deactivate_data_call_new(cid);
caps->tx_pending++; caps->mgr->tx_pending++;
DBG_(caps, "cid=%u, tx_pending=%d", cid, caps->tx_pending); DBG_(caps, "deactivating call %u", cid);
grilio_request_set_blocking(req, TRUE); grilio_request_set_blocking(req, TRUE);
grilio_request_set_timeout(req, DEACTIVATE_TIMEOUT_MS); grilio_request_set_timeout(req, DEACTIVATE_TIMEOUT_MS);
grilio_queue_send_request_full(caps->q, req, grilio_queue_send_request_full(caps->q, req,
@@ -1057,11 +1028,11 @@ static void ril_radio_caps_manager_deactivate_all
{ {
ril_radio_caps_manager_foreach_tx(self, ril_radio_caps_manager_foreach_tx(self,
ril_radio_caps_manager_deactivate_all_cb); ril_radio_caps_manager_deactivate_all_cb);
if (!ril_radio_caps_manager_tx_pending(self)) { if (!self->tx_pending) {
/* No data calls, submit ALLOW_DATA requests right away */ /* No data calls, submit ALLOW_DATA requests right away */
ril_radio_caps_manager_foreach_tx(self, ril_radio_caps_manager_foreach_tx(self,
ril_radio_caps_manager_data_off); ril_radio_caps_manager_data_off);
GASSERT(ril_radio_caps_manager_tx_pending(self)); GASSERT(self->tx_pending);
} }
} }
@@ -1284,24 +1255,6 @@ static GSList *ril_radio_caps_manager_empty_slots
return found; return found;
} }
static guint ril_radio_caps_manager_sim_count
(struct ril_radio_caps_manager *self)
{
const GPtrArray *list = self->caps_list;
guint i, count = 0;
for (i = 0; i < list->len; i++) {
const struct ril_radio_caps *caps = list->pdata[i];
if (caps->simcard->status->card_state ==
RIL_CARDSTATE_PRESENT) {
count++;
}
}
return count;
}
/** /**
* There could be no capability mismatch but LTE could be enabled for * There could be no capability mismatch but LTE could be enabled for
* the slot that has no SIM card in it. That's a waste, fix it. * the slot that has no SIM card in it. That's a waste, fix it.
@@ -1345,7 +1298,7 @@ static void ril_radio_caps_manager_check(struct ril_radio_caps_manager *self)
if (ril_radio_caps_manager_can_check(self)) { if (ril_radio_caps_manager_can_check(self)) {
const int first = ril_radio_caps_manager_first_mismatch(self); const int first = ril_radio_caps_manager_first_mismatch(self);
if (first >= 0 && ril_radio_caps_manager_sim_count(self) > 1) { if (first >= 0) {
if (ril_radio_caps_manager_update_caps(self, first)) { if (ril_radio_caps_manager_update_caps(self, first)) {
ril_radio_caps_manager_start_transaction(self); ril_radio_caps_manager_start_transaction(self);
} }
@@ -1368,7 +1321,7 @@ static gboolean ril_radio_caps_manager_check_cb(gpointer data)
static void ril_radio_caps_manager_recheck_later static void ril_radio_caps_manager_recheck_later
(struct ril_radio_caps_manager *self) (struct ril_radio_caps_manager *self)
{ {
if (!ril_radio_caps_manager_tx_pending(self)) { if (!self->tx_pending) {
if (self->check_id) { if (self->check_id) {
g_source_remove(self->check_id); g_source_remove(self->check_id);
self->check_id = 0; self->check_id = 0;
@@ -1381,7 +1334,7 @@ static void ril_radio_caps_manager_recheck_later
static void ril_radio_caps_manager_schedule_check static void ril_radio_caps_manager_schedule_check
(struct ril_radio_caps_manager *self) (struct ril_radio_caps_manager *self)
{ {
if (!self->check_id && !ril_radio_caps_manager_tx_pending(self)) { if (!self->check_id && !self->tx_pending) {
self->check_id = g_idle_add(ril_radio_caps_manager_check_cb, self->check_id = g_idle_add(ril_radio_caps_manager_check_cb,
self); self);
} }

View File

@@ -108,9 +108,8 @@ struct ril_sim_io_response {
guint data_len; guint data_len;
}; };
struct ril_sim_cbd_io { struct ril_sim_cbd {
struct ril_sim *sd; struct ril_sim *sd;
struct ril_sim_card *card;
union _ofono_sim_cb { union _ofono_sim_cb {
ofono_sim_file_info_cb_t file_info; ofono_sim_file_info_cb_t file_info;
ofono_sim_read_cb_t read; ofono_sim_read_cb_t read;
@@ -180,43 +179,24 @@ static const struct ril_sim_retry_query ril_sim_retry_query_types[] = {
#define DBG_(sd,fmt,args...) DBG("%s" fmt, (sd)->log_prefix, ##args) #define DBG_(sd,fmt,args...) DBG("%s" fmt, (sd)->log_prefix, ##args)
#define ril_sim_cbd_free g_free
static inline struct ril_sim *ril_sim_get_data(struct ofono_sim *sim) static inline struct ril_sim *ril_sim_get_data(struct ofono_sim *sim)
{ {
return ofono_sim_get_data(sim); return ofono_sim_get_data(sim);
} }
static struct ril_sim_cbd_io *ril_sim_cbd_io_new(struct ril_sim *sd, void *cb, static struct ril_sim_cbd *ril_sim_cbd_new(struct ril_sim *sd, void *cb,
void *data) void *data)
{ {
struct ril_sim_cbd_io *cbd = g_new0(struct ril_sim_cbd_io, 1); struct ril_sim_cbd *cbd = g_new0(struct ril_sim_cbd, 1);
cbd->sd = sd; cbd->sd = sd;
cbd->cb.ptr = cb; cbd->cb.ptr = cb;
cbd->data = data; cbd->data = data;
cbd->card = ril_sim_card_ref(sd->card);
return cbd; return cbd;
} }
static void ril_sim_cbd_io_free(void *data)
{
struct ril_sim_cbd_io *cbd = data;
ril_sim_card_sim_io_finished(cbd->card, cbd->req_id);
ril_sim_card_unref(cbd->card);
g_free(cbd);
}
static void ril_sim_cbd_io_start(struct ril_sim_cbd_io *cbd, GRilIoRequest* req,
guint code, GRilIoChannelResponseFunc cb)
{
struct ril_sim *sd = cbd->sd;
cbd->req_id = grilio_queue_send_request_full(sd->q, req, code,
cb, ril_sim_cbd_io_free, cbd);
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
}
static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc, static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
void *user_data) void *user_data)
{ {
@@ -275,6 +255,11 @@ static void ril_sim_pin_req_done(gpointer ptr)
} }
} }
static const char *ril_sim_app_id(struct ril_sim *sd)
{
return sd->card->app ? sd->card->app->aid : NULL;
}
int ril_sim_app_type(struct ofono_sim *sim) int ril_sim_app_type(struct ofono_sim *sim)
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
@@ -444,13 +429,14 @@ static void ril_sim_io_response_free(struct ril_sim_io_response *res)
static void ril_sim_file_info_cb(GRilIoChannel *io, int status, static void ril_sim_file_info_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_sim_cbd_io *cbd = user_data; struct ril_sim_cbd *cbd = user_data;
ofono_sim_file_info_cb_t cb = cbd->cb.file_info; ofono_sim_file_info_cb_t cb = cbd->cb.file_info;
struct ril_sim *sd = cbd->sd; struct ril_sim *sd = cbd->sd;
struct ril_sim_io_response *res = NULL; struct ril_sim_io_response *res = NULL;
struct ofono_error error; struct ofono_error error;
DBG_(sd, ""); DBG_(sd, "");
ril_sim_card_sim_io_finished(sd->card, cbd->req_id);
ril_error_init_failure(&error); ril_error_init_failure(&error);
res = ril_sim_parse_io_response(data, len); res = ril_sim_parse_io_response(data, len);
@@ -494,13 +480,12 @@ static void ril_sim_file_info_cb(GRilIoChannel *io, int status,
static void ril_sim_request_io(struct ril_sim *sd, guint cmd, int fileid, static void ril_sim_request_io(struct ril_sim *sd, guint cmd, int fileid,
guint p1, guint p2, guint p3, const char *hex_data, guint p1, guint p2, guint p3, const char *hex_data,
const guchar *path, guint path_len, const guchar *path, guint path_len,
GRilIoChannelResponseFunc cb, struct ril_sim_cbd_io *cbd) GRilIoChannelResponseFunc cb, struct ril_sim_cbd *cbd)
{ {
GRilIoRequest *req = grilio_request_new(); GRilIoRequest *req = grilio_request_new();
DBG_(sd, "cmd=0x%.2X,efid=0x%.4X,%d,%d,%d,%s,pin2=(null),aid=%s", DBG_(sd, "cmd=0x%.2X,efid=0x%.4X,%d,%d,%d,%s,pin2=(null),aid=%s",
cmd, fileid, p1, p2, p3, hex_data, cmd, fileid, p1, p2, p3, hex_data, ril_sim_app_id(sd));
ril_sim_card_app_aid(sd->card));
grilio_request_append_int32(req, cmd); grilio_request_append_int32(req, cmd);
grilio_request_append_int32(req, fileid); grilio_request_append_int32(req, fileid);
@@ -510,11 +495,13 @@ static void ril_sim_request_io(struct ril_sim *sd, guint cmd, int fileid,
grilio_request_append_int32(req, p3); /* P3 */ grilio_request_append_int32(req, p3); /* P3 */
grilio_request_append_utf8(req, hex_data); /* data; only for writes */ grilio_request_append_utf8(req, hex_data); /* data; only for writes */
grilio_request_append_utf8(req, NULL); /* pin2; only for writes */ grilio_request_append_utf8(req, NULL); /* pin2; only for writes */
grilio_request_append_utf8(req, ril_sim_card_app_aid(sd->card)); grilio_request_append_utf8(req, ril_sim_app_id(sd));
grilio_request_set_blocking(req, TRUE); grilio_request_set_blocking(req, TRUE);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000); grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_IO, cb); cbd->req_id = grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_SIM_IO, cb, ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req); grilio_request_unref(req);
} }
@@ -524,19 +511,19 @@ static void ril_sim_ofono_read_file_info(struct ofono_sim *sim, int fileid,
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
ril_sim_request_io(sd, CMD_GET_RESPONSE, fileid, 0, 0, 15, NULL, ril_sim_request_io(sd, CMD_GET_RESPONSE, fileid, 0, 0, 15, NULL,
path, len, ril_sim_file_info_cb, path, len, ril_sim_file_info_cb, ril_sim_cbd_new(sd, cb, data));
ril_sim_cbd_io_new(sd, cb, data));
} }
static void ril_sim_read_cb(GRilIoChannel *io, int status, static void ril_sim_read_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_sim_cbd_io *cbd = user_data; struct ril_sim_cbd *cbd = user_data;
ofono_sim_read_cb_t cb = cbd->cb.read; ofono_sim_read_cb_t cb = cbd->cb.read;
struct ril_sim_io_response *res; struct ril_sim_io_response *res;
struct ofono_error err; struct ofono_error err;
DBG_(cbd->sd, ""); DBG_(cbd->sd, "");
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
res = ril_sim_parse_io_response(data, len); res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) { if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
@@ -555,7 +542,7 @@ static void ril_sim_read(struct ofono_sim *sim, guint cmd, int fileid,
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
ril_sim_request_io(sd, cmd, fileid, p1, p2, p3, NULL, path, path_len, ril_sim_request_io(sd, cmd, fileid, p1, p2, p3, NULL, path, path_len,
ril_sim_read_cb, ril_sim_cbd_io_new(sd, cb, data)); ril_sim_read_cb, ril_sim_cbd_new(sd, cb, data));
} }
static void ril_sim_ofono_read_file_transparent(struct ofono_sim *sim, static void ril_sim_ofono_read_file_transparent(struct ofono_sim *sim,
@@ -585,12 +572,13 @@ static void ril_sim_ofono_read_file_cyclic(struct ofono_sim *sim, int fileid,
static void ril_sim_write_cb(GRilIoChannel *io, int status, static void ril_sim_write_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_sim_cbd_io *cbd = user_data; struct ril_sim_cbd *cbd = user_data;
ofono_sim_write_cb_t cb = cbd->cb.write; ofono_sim_write_cb_t cb = cbd->cb.write;
struct ril_sim_io_response *res; struct ril_sim_io_response *res;
struct ofono_error err; struct ofono_error err;
DBG_(cbd->sd, ""); DBG_(cbd->sd, "");
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
res = ril_sim_parse_io_response(data, len); res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) { if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
@@ -611,7 +599,7 @@ static void ril_sim_write(struct ofono_sim *sim, guint cmd, int fileid,
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
char *hex_data = encode_hex(value, length, 0); char *hex_data = encode_hex(value, length, 0);
ril_sim_request_io(sd, cmd, fileid, p1, p2, length, hex_data, path, ril_sim_request_io(sd, cmd, fileid, p1, p2, length, hex_data, path,
path_len, ril_sim_write_cb, ril_sim_cbd_io_new(sd, cb, data)); path_len, ril_sim_write_cb, ril_sim_cbd_new(sd, cb, data));
g_free(hex_data); g_free(hex_data);
} }
@@ -648,10 +636,12 @@ static void ril_sim_write_file_cyclic(struct ofono_sim *sim, int fileid,
static void ril_sim_get_imsi_cb(GRilIoChannel *io, int status, static void ril_sim_get_imsi_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ril_sim_cbd_io *cbd = user_data; struct ril_sim_cbd *cbd = user_data;
ofono_sim_imsi_cb_t cb = cbd->cb.imsi; ofono_sim_imsi_cb_t cb = cbd->cb.imsi;
struct ofono_error error; struct ofono_error error;
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
if (status == RIL_E_SUCCESS) { if (status == RIL_E_SUCCESS) {
gchar *imsi; gchar *imsi;
GRilIoParser rilp; GRilIoParser rilp;
@@ -676,8 +666,8 @@ static void ril_sim_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
void *data) void *data)
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
const char *app_id = ril_sim_card_app_aid(sd->card); const char *app_id = ril_sim_app_id(sd);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data); struct ril_sim_cbd *cbd = ril_sim_cbd_new(sd, cb, data);
GRilIoRequest *req = grilio_request_array_utf8_new(1, app_id); GRilIoRequest *req = grilio_request_array_utf8_new(1, app_id);
DBG_(sd, "%s", app_id); DBG_(sd, "%s", app_id);
@@ -689,8 +679,10 @@ static void ril_sim_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
*/ */
grilio_request_set_retry(req, RIL_RETRY_MS, -1); grilio_request_set_retry(req, RIL_RETRY_MS, -1);
grilio_request_set_blocking(req, TRUE); grilio_request_set_blocking(req, TRUE);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_GET_IMSI, cbd->req_id = grilio_queue_send_request_full(sd->q, req,
ril_sim_get_imsi_cb); RIL_REQUEST_GET_IMSI, ril_sim_get_imsi_cb,
ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req); grilio_request_unref(req);
} }
@@ -898,22 +890,25 @@ static int ril_sim_parse_retry_count(const void *data, guint len)
static GRilIoRequest *ril_sim_enter_sim_pin_req(struct ril_sim *sd, static GRilIoRequest *ril_sim_enter_sim_pin_req(struct ril_sim *sd,
const char *pin) const char *pin)
{ {
/* if (sd->card->app) {
* If there's no AID then so be it... Some /*
* adaptations (namely, MTK) don't provide it * If there's no AID then so be it... Some
* but don't seem to require it either. * adaptations (namely, MTK) don't provide it
*/ * but don't seem to require it either.
GRilIoRequest *req = grilio_request_array_utf8_new(2, pin, */
ril_sim_card_app_aid(sd->card)); GRilIoRequest *req = grilio_request_array_utf8_new(2,
pin, sd->card->app->aid);
grilio_request_set_blocking(req, TRUE); grilio_request_set_blocking(req, TRUE);
return req; return req;
}
return NULL;
} }
static GRilIoRequest *ril_sim_enter_sim_puk_req(struct ril_sim *sd, static GRilIoRequest *ril_sim_enter_sim_puk_req(struct ril_sim *sd,
const char *puk, const char *pin) const char *puk, const char *pin)
{ {
const char *app_id = ril_sim_card_app_aid(sd->card); const char *app_id = ril_sim_app_id(sd);
if (app_id) { if (app_id) {
GRilIoRequest *req = grilio_request_array_utf8_new(3, GRilIoRequest *req = grilio_request_array_utf8_new(3,
puk, pin, app_id); puk, pin, app_id);
@@ -1215,7 +1210,7 @@ static void ril_sim_pin_send(struct ofono_sim *sim, const char *passwd,
GRilIoRequest *req = ril_sim_enter_sim_pin_req(sd, passwd); GRilIoRequest *req = ril_sim_enter_sim_pin_req(sd, passwd);
if (req) { if (req) {
DBG_(sd, "%s,aid=%s", passwd, ril_sim_card_app_aid(sd->card)); DBG_(sd, "%s,aid=%s", passwd, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req, grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PIN, ril_sim_pin_change_state_cb, RIL_REQUEST_ENTER_SIM_PIN, ril_sim_pin_change_state_cb,
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd, ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
@@ -1242,7 +1237,10 @@ static guint ril_perso_change_state(struct ofono_sim *sim,
case OFONO_SIM_PASSWORD_PHNET_PIN: case OFONO_SIM_PASSWORD_PHNET_PIN:
if (!enable) { if (!enable) {
code = RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION; code = RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION;
req = grilio_request_array_utf8_new(1, passwd); req = grilio_request_sized_new(12);
grilio_request_append_int32(req,
RIL_PERSOSUBSTATE_SIM_NETWORK);
grilio_request_append_utf8(req, passwd);
} else { } else {
DBG_(sd, "Not supported, enable=%d", enable); DBG_(sd, "Not supported, enable=%d", enable);
} }
@@ -1291,7 +1289,7 @@ static void ril_sim_pin_change_state(struct ofono_sim *sim,
const char *passwd, ofono_sim_lock_unlock_cb_t cb, void *data) const char *passwd, ofono_sim_lock_unlock_cb_t cb, void *data)
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
const char *app_id = ril_sim_card_app_aid(sd->card); const char *app_id = ril_sim_app_id(sd);
const char *type_str = ril_sim_facility_code(passwd_type); const char *type_str = ril_sim_facility_code(passwd_type);
struct ofono_error error; struct ofono_error error;
guint id = 0; guint id = 0;
@@ -1329,7 +1327,7 @@ static void ril_sim_pin_send_puk(struct ofono_sim *sim,
if (req) { if (req) {
DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd, DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd,
ril_sim_card_app_aid(sd->card)); ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req, grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PUK, ril_sim_pin_change_state_cb, RIL_REQUEST_ENTER_SIM_PUK, ril_sim_pin_change_state_cb,
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd, ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
@@ -1349,7 +1347,7 @@ static void ril_sim_change_passwd(struct ofono_sim *sim,
ofono_sim_lock_unlock_cb_t cb, void *data) ofono_sim_lock_unlock_cb_t cb, void *data)
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
const char *app_id = ril_sim_card_app_aid(sd->card); const char *app_id = ril_sim_app_id(sd);
GRilIoRequest *req = grilio_request_array_utf8_new(3, GRilIoRequest *req = grilio_request_array_utf8_new(3,
old_passwd, new_passwd, app_id); old_passwd, new_passwd, app_id);
@@ -1367,9 +1365,11 @@ static void ril_sim_query_facility_lock_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct ofono_error error; struct ofono_error error;
struct ril_sim_cbd_io *cbd = user_data; struct ril_sim_cbd *cbd = user_data;
ofono_query_facility_lock_cb_t cb = cbd->cb.query_facility_lock; ofono_query_facility_lock_cb_t cb = cbd->cb.query_facility_lock;
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
if (status == RIL_E_SUCCESS) { if (status == RIL_E_SUCCESS) {
int locked = 0; int locked = 0;
GRilIoParser rilp; GRilIoParser rilp;
@@ -1399,9 +1399,9 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
{ {
struct ril_sim *sd = ril_sim_get_data(sim); struct ril_sim *sd = ril_sim_get_data(sim);
const char *type_str = ril_sim_facility_code(type); const char *type_str = ril_sim_facility_code(type);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data); struct ril_sim_cbd *cbd = ril_sim_cbd_new(sd, cb, data);
GRilIoRequest *req = grilio_request_array_utf8_new(4, GRilIoRequest *req = grilio_request_array_utf8_new(4,
type_str, "", "0" /* class */, ril_sim_card_app_aid(sd->card)); type_str, "", "0" /* class */, ril_sim_app_id(sd));
/* Make sure that this request gets completed sooner or later */ /* Make sure that this request gets completed sooner or later */
grilio_request_set_timeout(req, FAC_LOCK_QUERY_TIMEOUT_SECS * 1000); grilio_request_set_timeout(req, FAC_LOCK_QUERY_TIMEOUT_SECS * 1000);
@@ -1409,8 +1409,10 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
grilio_request_set_retry_func(req, ril_sim_query_facility_lock_retry); grilio_request_set_retry_func(req, ril_sim_query_facility_lock_retry);
DBG_(sd, "%s", type_str); DBG_(sd, "%s", type_str);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_QUERY_FACILITY_LOCK, cbd->req_id = grilio_queue_send_request_full(sd->q, req,
ril_sim_query_facility_lock_cb); RIL_REQUEST_QUERY_FACILITY_LOCK, ril_sim_query_facility_lock_cb,
ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req); grilio_request_unref(req);
} }

View File

@@ -77,13 +77,9 @@ void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
void ril_sim_card_remove_handlers(struct ril_sim_card *sc, gulong *ids, int n); void ril_sim_card_remove_handlers(struct ril_sim_card *sc, gulong *ids, int n);
/* Inline wrappers */ /* Inline wrappers */
static inline enum ril_app_type ril_sim_card_app_type(struct ril_sim_card *sc) static inline enum ril_app_type
ril_sim_card_app_type(struct ril_sim_card *sc)
{ return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; } { return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; }
static inline const char *ril_sim_card_app_aid(struct ril_sim_card *sc)
{ return (sc && sc->app) ? sc->app->aid : NULL; }
#define ril_sim_card_remove_all_handlers(net, ids) \
ril_sim_card_remove_handlers(net, ids, G_N_ELEMENTS(ids))
#endif /* RIL_SIM_CARD_H */ #endif /* RIL_SIM_CARD_H */

View File

@@ -209,43 +209,3 @@ socket=/dev/socket/rild
# Default is false (use RIL_REQUEST_DEVICE_IDENTITY) # Default is false (use RIL_REQUEST_DEVICE_IDENTITY)
# #
#legacyImeiQuery=false #legacyImeiQuery=false
# Some devices don't support LTE RAT mode PREF_NET_TYPE_LTE_GSM_WCDMA.
# This option allows to set a custom LTE mode.
#
# The default is 9 (PREF_NET_TYPE_LTE_GSM_WCDMA)
#
#lteNetworkMode=9
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
#
# The default is 20000 (20 seconds)
#
#networkModeTimeout=20000
# Cycle radio power at startup.
#
# The default is true (cycle the power)
#
#radioPowerCycle=true
# With some RILs it seems to be necessary to kick (RIL_REQUEST_RADIO_POWER)
# the modems with power on after one of the modems has been powered off.
# Otherwise bad things may happen (like the modem never registering
# on the network).
#
# On the other hand, with some RILs it's causing some trouble (like this
# extra RIL_REQUEST_RADIO_POWER getting stuck indefinitely).
#
# The default is true for historical reasons
#
#confirmRadioPowerOn=true
# Normally we should be able to have two simultaneously active data
# contexts - one for mobile data and one for MMS. Some devices however
# require that mobile data is disconnected before we can send or receive
# MMS. In other words, activation of the second data context fails.
#
# The default is false (more than one context is supported)
#
#singleDataContext=false

View File

@@ -51,12 +51,8 @@ struct ril_vendor_hook;
struct ril_slot_config { struct ril_slot_config {
guint slot; guint slot;
enum ofono_radio_access_mode techs; enum ofono_radio_access_mode techs;
int lte_network_mode;
int network_mode_timeout;
gboolean query_available_band_mode; gboolean query_available_band_mode;
gboolean empty_pin_query; gboolean empty_pin_query;
gboolean radio_power_cycle;
gboolean confirm_radio_power_on;
gboolean enable_voicecall; gboolean enable_voicecall;
gboolean enable_cbs; gboolean enable_cbs;
GUtilInts *local_hangup_reasons; GUtilInts *local_hangup_reasons;

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2018 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -20,8 +20,6 @@
#include "smsutil.h" #include "smsutil.h"
#include "util.h" #include "util.h"
#define USSD_CANCEL_TIMEOUT_SEC (20)
struct ril_ussd { struct ril_ussd {
struct ofono_ussd *ussd; struct ofono_ussd *ussd;
GRilIoChannel *io; GRilIoChannel *io;
@@ -116,14 +114,11 @@ static void ril_ussd_cancel(struct ofono_ussd *ussd,
ofono_ussd_cb_t cb, void *data) ofono_ussd_cb_t cb, void *data)
{ {
struct ril_ussd *ud = ril_ussd_get_data(ussd); struct ril_ussd *ud = ril_ussd_get_data(ussd);
GRilIoRequest *req = grilio_request_new();
ofono_info("send ussd cancel"); ofono_info("send ussd cancel");
grilio_request_set_timeout(req, USSD_CANCEL_TIMEOUT_SEC * 1000); grilio_queue_send_request_full(ud->q, NULL, RIL_REQUEST_CANCEL_USSD,
grilio_queue_send_request_full(ud->q, req, RIL_REQUEST_CANCEL_USSD,
ril_ussd_cancel_cb, ril_ussd_cbd_free, ril_ussd_cancel_cb, ril_ussd_cbd_free,
ril_ussd_cbd_new(cb, data)); ril_ussd_cbd_new(cb, data));
grilio_request_unref(req);
} }
static void ril_ussd_notify(GRilIoChannel *io, guint code, static void ril_ussd_notify(GRilIoChannel *io, guint code,

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2018 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -18,10 +18,10 @@
#include <grilio_channel.h> #include <grilio_channel.h>
#include <gutil_misc.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#include <limits.h>
#include "common.h" #include "common.h"
#include "netreg.h" #include "netreg.h"
@@ -326,7 +326,7 @@ int ril_parse_tech(const char *stech, int *ril_tech)
{ {
int access_tech = -1; int access_tech = -1;
int tech = -1; int tech = -1;
if (gutil_parse_int(stech, 0, &tech)) { if (ril_parse_int(stech, 0, &tech)) {
switch (tech) { switch (tech) {
case RADIO_TECH_GPRS: case RADIO_TECH_GPRS:
case RADIO_TECH_GSM: case RADIO_TECH_GSM:
@@ -411,6 +411,26 @@ gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op)
return FALSE; return FALSE;
} }
gboolean ril_parse_int(const char *str, int base, int *value)
{
gboolean ok = FALSE;
if (str && str[0]) {
char *str2 = g_strstrip(g_strdup(str));
char *end = str2;
long l;
errno = 0;
l = strtol(str2, &end, base);
ok = !*end && errno != ERANGE && l >= INT_MIN && l <= INT_MAX;
if (ok && value) {
*value = (int)l;
}
g_free(str2);
}
return ok;
}
/* /*
* Local Variables: * Local Variables:
* mode: C * mode: C

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2018 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,7 @@ const char *ril_unsol_event_to_string(guint event);
const char *ril_radio_state_to_string(int radio_state); const char *ril_radio_state_to_string(int radio_state);
int ril_parse_tech(const char *stech, int *ril_tech); int ril_parse_tech(const char *stech, int *ril_tech);
gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op); gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op);
gboolean ril_parse_int(const char *str, int base, int *value);
#define ril_error_init_ok(err) \ #define ril_error_init_ok(err) \
((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_NO_ERROR) ((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_NO_ERROR)

View File

@@ -27,7 +27,6 @@
#include <grilio_queue.h> #include <grilio_queue.h>
#include <gutil_macros.h> #include <gutil_macros.h>
#include <gutil_misc.h>
#include "ofono.h" #include "ofono.h"
@@ -84,7 +83,6 @@ struct ril_vendor_hook_mtk_auto {
struct ril_mtk_msg { struct ril_mtk_msg {
gboolean attach_apn_has_roaming_protocol; gboolean attach_apn_has_roaming_protocol;
guint request_resume_registration; guint request_resume_registration;
guint request_set_call_indication;
/* See ril_vendor_mtk_auto_detect_event */ /* See ril_vendor_mtk_auto_detect_event */
#define unsol_msgs unsol_ps_network_state_changed #define unsol_msgs unsol_ps_network_state_changed
@@ -99,7 +97,6 @@ struct ril_mtk_msg {
static const struct ril_mtk_msg msg_mtk1 = { static const struct ril_mtk_msg msg_mtk1 = {
.attach_apn_has_roaming_protocol = TRUE, .attach_apn_has_roaming_protocol = TRUE,
.request_resume_registration = 2050, .request_resume_registration = 2050,
.request_set_call_indication = 2065,
.unsol_ps_network_state_changed = 3012, .unsol_ps_network_state_changed = 3012,
.unsol_registration_suspended = 3021, .unsol_registration_suspended = 3021,
.unsol_incoming_call_indication = 3037, .unsol_incoming_call_indication = 3037,
@@ -109,7 +106,6 @@ static const struct ril_mtk_msg msg_mtk1 = {
static const struct ril_mtk_msg msg_mtk2 = { static const struct ril_mtk_msg msg_mtk2 = {
.attach_apn_has_roaming_protocol = FALSE, .attach_apn_has_roaming_protocol = FALSE,
.request_resume_registration = 2065, .request_resume_registration = 2065,
.request_set_call_indication = 2086,
.unsol_ps_network_state_changed = 3015, .unsol_ps_network_state_changed = 3015,
.unsol_registration_suspended = 3024, .unsol_registration_suspended = 3024,
.unsol_incoming_call_indication = 3042, .unsol_incoming_call_indication = 3042,
@@ -136,8 +132,6 @@ static const char *ril_vendor_mtk_request_to_string
if (request == msg->request_resume_registration) { if (request == msg->request_resume_registration) {
return "MTK_RESUME_REGISTRATION"; return "MTK_RESUME_REGISTRATION";
} else if (request == msg->request_set_call_indication) {
return "MTK_SET_CALL_INDICATION";
} else { } else {
return NULL; return NULL;
} }
@@ -346,55 +340,12 @@ static void ril_vendor_mtk_ps_network_state_changed(GRilIoChannel *io,
ril_network_query_registration_state(self->network); ril_network_query_registration_state(self->network);
} }
static void ril_vendor_mtk_incoming_call_indication(GRilIoChannel *io, guint id, static void ril_vendor_mtk_call_state_changed(GRilIoChannel *io,
const void *data, guint len, void *user_data) guint id, const void *data, guint len, void *user_data)
{ {
struct ril_vendor_hook_mtk *self = user_data; /* Ignore the payload, let ril_voicecall.c do its normal stuff */
const struct ril_mtk_msg *msg = self->msg; grilio_channel_inject_unsol_event(io,
GRilIoRequest* req = NULL; RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
GASSERT(id == msg->unsol_incoming_call_indication);
if (msg->request_set_call_indication) {
int nparams, cid, seq;
gchar *call_id = NULL, *seq_no = NULL;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &nparams) && nparams >= 5 &&
(call_id = grilio_parser_get_utf8(&rilp)) != NULL &&
grilio_parser_skip_string(&rilp) /* number */ &&
grilio_parser_skip_string(&rilp) /* type */ &&
grilio_parser_skip_string(&rilp) /* call_mode */ &&
(seq_no = grilio_parser_get_utf8(&rilp)) != NULL &&
gutil_parse_int(call_id, 10, &cid) &&
gutil_parse_int(seq_no, 10, &seq)) {
DBG("slot=%u,cid=%d,seq=%d", self->slot, cid, seq);
req = grilio_request_new();
grilio_request_append_int32(req, 3); /* Param count */
/* mode - IMS_ALLOW_INCOMING_CALL_INDICATION: */
grilio_request_append_int32(req, 0);
grilio_request_append_int32(req, cid);
grilio_request_append_int32(req, seq);
} else {
DBG("failed to parse INCOMING_CALL_INDICATION");
}
g_free(call_id);
g_free(seq_no);
}
if (req) {
grilio_queue_send_request(self->q, req,
msg->request_set_call_indication);
grilio_request_unref(req);
} else {
/* Let ril_voicecall.c know that something happened */
grilio_channel_inject_unsol_event(io,
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
}
} }
static GRilIoRequest *ril_vendor_mtk_data_call_req static GRilIoRequest *ril_vendor_mtk_data_call_req
@@ -492,7 +443,7 @@ static void ril_vendor_mtk_hook_subscribe(struct ril_vendor_hook_mtk *self)
if (msg->unsol_incoming_call_indication) { if (msg->unsol_incoming_call_indication) {
self->ril_event_id[MTK_EVENT_INCOMING_CALL_INDICATION] = self->ril_event_id[MTK_EVENT_INCOMING_CALL_INDICATION] =
grilio_channel_add_unsol_event_handler(self->io, grilio_channel_add_unsol_event_handler(self->io,
ril_vendor_mtk_incoming_call_indication, ril_vendor_mtk_call_state_changed,
msg->unsol_incoming_call_indication, self); msg->unsol_incoming_call_indication, self);
} }
} }

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2018 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@@ -587,75 +587,39 @@ static void ril_voicecall_submit_hangup_req(struct ofono_voicecall *vc,
grilio_request_unref(ioreq); grilio_request_unref(ioreq);
} }
static void ril_voicecall_hangup(struct ofono_voicecall *vc, static void ril_voicecall_hangup_all(struct ofono_voicecall *vc,
gboolean (*filter)(struct ofono_call *call),
ofono_voicecall_cb_t cb, void *data) ofono_voicecall_cb_t cb, void *data)
{ {
struct ril_voicecall *vd = ril_voicecall_get_data(vc); struct ril_voicecall *vd = ril_voicecall_get_data(vc);
struct ril_voicecall_request_data *req = NULL;
GSList *l;
/* if (vd->calls) {
* Here the idea is that we submit (potentially) multiple GSList *l;
* hangup requests to RIL and invoke the callback after struct ril_voicecall_request_data *req =
* the last request has completed (pending call count ril_voicecall_request_data_new(vc, cb, data);
* becomes zero).
*/
for (l = vd->calls; l; l = l->next) {
struct ofono_call *call = l->data;
if (!filter || filter(call)) { /*
if (!req) { * Here the idea is that we submit (potentially) multiple
req = ril_voicecall_request_data_new(vc, cb, * hangup requests to RIL and invoke the callback after
data); * the last request has completed (pending call count
} * becomes zero).
*/
for (l = vd->calls; l; l = l->next) {
struct ofono_call *call = l->data;
/* Send request to RIL */ /* Send request to RIL */
DBG("Hanging up call with id %d", call->id); DBG("Hanging up call with id %d", call->id);
ril_voicecall_submit_hangup_req(vc, call->id, req); ril_voicecall_submit_hangup_req(vc, call->id, req);
} else {
DBG("Skipping call with id %d", call->id);
} }
}
if (req) { /* Release our reference */
/* Release our reference (if any) */
ril_voicecall_request_data_unref(req); ril_voicecall_request_data_unref(req);
} else { } else {
/* No requests were submitted */ /* No calls */
struct ofono_error error; struct ofono_error error;
cb(ril_error_ok(&error), data); cb(ril_error_ok(&error), data);
} }
} }
static gboolean ril_voicecall_hangup_active_filter(struct ofono_call *call)
{
switch (call->status) {
case CALL_STATUS_ACTIVE:
case CALL_STATUS_DIALING:
case CALL_STATUS_ALERTING:
case CALL_STATUS_INCOMING:
return TRUE;
case CALL_STATUS_HELD:
case CALL_STATUS_WAITING:
case CALL_STATUS_DISCONNECTED:
break;
}
return FALSE;
}
static void ril_voicecall_hangup_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
ril_voicecall_hangup(vc, ril_voicecall_hangup_active_filter, cb, data);
}
static void ril_voicecall_hangup_all(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
ril_voicecall_hangup(vc, NULL, cb, data);
}
static void ril_voicecall_release_specific(struct ofono_voicecall *vc, static void ril_voicecall_release_specific(struct ofono_voicecall *vc,
int id, ofono_voicecall_cb_t cb, void *data) int id, ofono_voicecall_cb_t cb, void *data)
{ {
@@ -693,7 +657,7 @@ static void ril_voicecall_supp_svc_notification_event(GRilIoChannel *io,
grilio_parser_get_int32(&rilp, &type); grilio_parser_get_int32(&rilp, &type);
grilio_parser_get_int32(&rilp, &code); grilio_parser_get_int32(&rilp, &code);
grilio_parser_get_int32(&rilp, &index); grilio_parser_get_int32(&rilp, &index);
grilio_parser_get_int32(&rilp, &phone.type); grilio_parser_get_int32(&rilp, NULL);
tmp = grilio_parser_get_utf8(&rilp); tmp = grilio_parser_get_utf8(&rilp);
if (tmp) { if (tmp) {
@@ -847,7 +811,8 @@ static void ril_voicecall_set_udub(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data) ofono_voicecall_cb_t cb, void *data)
{ {
DBG(""); DBG("");
ril_voicecall_request(RIL_REQUEST_UDUB, vc, NULL, cb, data); ril_voicecall_request(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
vc, NULL, cb, data);
} }
static void ril_voicecall_enable_supp_svc(struct ril_voicecall *vd) static void ril_voicecall_enable_supp_svc(struct ril_voicecall *vd)
@@ -981,7 +946,6 @@ const struct ofono_voicecall_driver ril_voicecall_driver = {
.remove = ril_voicecall_remove, .remove = ril_voicecall_remove,
.dial = ril_voicecall_dial, .dial = ril_voicecall_dial,
.answer = ril_voicecall_answer, .answer = ril_voicecall_answer,
.hangup_active = ril_voicecall_hangup_active,
.hangup_all = ril_voicecall_hangup_all, .hangup_all = ril_voicecall_hangup_all,
.release_specific = ril_voicecall_release_specific, .release_specific = ril_voicecall_release_specific,
.send_tones = ril_voicecall_send_dtmf, .send_tones = ril_voicecall_send_dtmf,

View File

@@ -54,7 +54,7 @@ static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
unsigned int len = sizeof(saddr); unsigned int len = sizeof(saddr);
int fd; int fd;
struct ofono_emulator *em; struct ofono_emulator *em;
GList *i; struct ofono_modem *modem;
if (cond != G_IO_IN) if (cond != G_IO_IN)
return FALSE; return FALSE;
@@ -63,16 +63,15 @@ static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
if (fd == -1) if (fd == -1)
return FALSE; return FALSE;
DBG("Using all modems for emulator."); /* Pick the first powered modem */
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
em = ofono_emulator_create(GPOINTER_TO_INT(user)); em = ofono_emulator_create(modem, GPOINTER_TO_INT(user));
if (em == NULL)
if (em) {
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
ofono_emulator_register(em, fd);
} else
close(fd); close(fd);
else
ofono_emulator_register(em, fd);
return TRUE; return TRUE;
} }

View File

@@ -68,9 +68,8 @@ typedef void (*ofono_emulator_request_cb_t)(struct ofono_emulator *em,
struct ofono_emulator_request *req, struct ofono_emulator_request *req,
void *data); void *data);
struct ofono_emulator *ofono_emulator_create(enum ofono_emulator_type type); struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
void ofono_emulator_add_modem(struct ofono_emulator *em, enum ofono_emulator_type type);
struct ofono_modem *modem);
void ofono_emulator_register(struct ofono_emulator *em, int fd); void ofono_emulator_register(struct ofono_emulator *em, int fd);

View File

@@ -22,14 +22,12 @@ extern "C" {
#include <ofono/types.h> #include <ofono/types.h>
struct ofono_gprs;
struct ofono_gprs_context; struct ofono_gprs_context;
struct ofono_gprs_primary_context; struct ofono_gprs_primary_context;
/* If ctx is NULL then activation gets cancelled */ /* If ctx is NULL then activation gets cancelled */
typedef void (*ofono_gprs_filter_activate_cb_t) typedef void (*ofono_gprs_filter_activate_cb_t)
(const struct ofono_gprs_primary_context *ctx, void *data); (const struct ofono_gprs_primary_context *ctx, void *data);
typedef void (*ofono_gprs_filter_check_cb_t)(ofono_bool_t allow, void *data);
#define OFONO_GPRS_FILTER_PRIORITY_LOW (-100) #define OFONO_GPRS_FILTER_PRIORITY_LOW (-100)
#define OFONO_GPRS_FILTER_PRIORITY_DEFAULT (0) #define OFONO_GPRS_FILTER_PRIORITY_DEFAULT (0)
@@ -40,7 +38,7 @@ typedef void (*ofono_gprs_filter_check_cb_t)(ofono_bool_t allow, void *data);
* even if struct ofono_gprs_filter gets extended with new callbacks. * even if struct ofono_gprs_filter gets extended with new callbacks.
*/ */
#define OFONO_GPRS_FILTER_API_VERSION (1) #define OFONO_GPRS_FILTER_API_VERSION (0)
/* /*
* The filter callbacks either invoke the completion callback directly * The filter callbacks either invoke the completion callback directly
@@ -61,9 +59,6 @@ struct ofono_gprs_filter {
const struct ofono_gprs_primary_context *ctx, const struct ofono_gprs_primary_context *ctx,
ofono_gprs_filter_activate_cb_t cb, ofono_gprs_filter_activate_cb_t cb,
void *data); void *data);
/* API version 1 */
unsigned int (*filter_check)(struct ofono_gprs *gprs,
ofono_gprs_filter_check_cb_t cb, void *data);
}; };
int ofono_gprs_filter_register(const struct ofono_gprs_filter *filter); int ofono_gprs_filter_register(const struct ofono_gprs_filter *filter);

View File

@@ -83,8 +83,6 @@ void ofono_gprs_add_context(struct ofono_gprs *gprs,
void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid, void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid,
const char *apn); const char *apn);
void ofono_gprs_attached_update(struct ofono_gprs *gprs);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -29,9 +29,7 @@ extern "C" {
#include <ofono/types.h> #include <ofono/types.h>
struct ofono_modem; struct ofono_modem;
struct ofono_gprs;
struct ofono_sim; struct ofono_sim;
struct ofono_voicecall;
enum ofono_modem_type { enum ofono_modem_type {
OFONO_MODEM_TYPE_HARDWARE = 0, OFONO_MODEM_TYPE_HARDWARE = 0,
@@ -84,8 +82,6 @@ void ofono_modem_remove_interface(struct ofono_modem *modem,
const char *ofono_modem_get_path(struct ofono_modem *modem); const char *ofono_modem_get_path(struct ofono_modem *modem);
struct ofono_sim *ofono_modem_get_sim(struct ofono_modem *modem); struct ofono_sim *ofono_modem_get_sim(struct ofono_modem *modem);
struct ofono_gprs *ofono_modem_get_gprs(struct ofono_modem *modem);
struct ofono_voicecall *ofono_modem_get_voicecall(struct ofono_modem *modem);
void ofono_modem_set_data(struct ofono_modem *modem, void *data); void ofono_modem_set_data(struct ofono_modem *modem, void *data);
void *ofono_modem_get_data(struct ofono_modem *modem); void *ofono_modem_get_data(struct ofono_modem *modem);

View File

@@ -1,284 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __OFONO_RIL_CONSTANTS_H
#define __OFONO_RIL_CONSTANTS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Error Codes */
enum ril_status {
RIL_E_SUCCESS = 0,
RIL_E_RADIO_NOT_AVAILABLE = 1,
RIL_E_GENERIC_FAILURE = 2,
RIL_E_PASSWORD_INCORRECT = 3,
RIL_E_SIM_PIN2 = 4,
RIL_E_SIM_PUK2 = 5,
RIL_E_REQUEST_NOT_SUPPORTED = 6,
RIL_E_CANCELLED = 7,
RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL = 8,
RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9,
RIL_E_SMS_SEND_FAIL_RETRY = 10,
RIL_E_SIM_ABSENT = 11,
RIL_E_SUBSCRIPTION_NOT_AVAILABLE = 12,
RIL_E_MODE_NOT_SUPPORTED = 13,
RIL_E_FDN_CHECK_FAILURE = 14,
RIL_E_ILLEGAL_SIM_OR_ME = 15,
RIL_E_MISSING_RESOURCE = 16,
RIL_E_NO_SUCH_ELEMENT = 17,
RIL_E_DIAL_MODIFIED_TO_USSD = 18,
RIL_E_DIAL_MODIFIED_TO_SS = 19,
RIL_E_DIAL_MODIFIED_TO_DIAL = 20,
RIL_E_USSD_MODIFIED_TO_DIAL = 21,
RIL_E_USSD_MODIFIED_TO_SS = 22,
RIL_E_USSD_MODIFIED_TO_USSD = 23,
RIL_E_SS_MODIFIED_TO_DIAL = 24,
RIL_E_SS_MODIFIED_TO_USSD = 25,
RIL_E_SUBSCRIPTION_NOT_SUPPORTED = 26,
RIL_E_SS_MODIFIED_TO_SS = 27,
RIL_E_LCE_NOT_SUPPORTED = 36,
RIL_E_NO_MEMORY = 37,
RIL_E_INTERNAL_ERR = 38,
RIL_E_SYSTEM_ERR = 39,
RIL_E_MODEM_ERR = 40,
RIL_E_INVALID_STATE = 41,
RIL_E_NO_RESOURCES = 42,
RIL_E_SIM_ERR = 43,
RIL_E_INVALID_ARGUMENTS = 44,
RIL_E_INVALID_SIM_STATE = 45,
RIL_E_INVALID_MODEM_STATE = 46,
RIL_E_INVALID_CALL_ID = 47,
RIL_E_NO_SMS_TO_ACK = 48,
RIL_E_NETWORK_ERR = 49,
RIL_E_REQUEST_RATE_LIMITED = 50,
RIL_E_SIM_BUSY = 51,
RIL_E_SIM_FULL = 52,
RIL_E_NETWORK_REJECT = 53,
RIL_E_OPERATION_NOT_ALLOWED = 54,
RIL_E_EMPTY_RECORD = 55,
RIL_E_INVALID_SMS_FORMAT = 56,
RIL_E_ENCODING_ERR = 57,
RIL_E_INVALID_SMSC_ADDRESS = 58,
RIL_E_NO_SUCH_ENTRY = 59,
RIL_E_NETWORK_NOT_READY = 60,
RIL_E_NOT_PROVISIONED = 61,
RIL_E_NO_SUBSCRIPTION = 62,
RIL_E_NO_NETWORK_FOUND = 63,
RIL_E_DEVICE_IN_USE = 64,
RIL_E_ABORTED = 65,
RIL_E_INVALID_RESPONSE = 66
};
/* RIL Request Messages, ofono -> rild */
#define RIL_REQUEST_GET_SIM_STATUS 1
#define RIL_REQUEST_ENTER_SIM_PIN 2
#define RIL_REQUEST_ENTER_SIM_PUK 3
#define RIL_REQUEST_ENTER_SIM_PIN2 4
#define RIL_REQUEST_ENTER_SIM_PUK2 5
#define RIL_REQUEST_CHANGE_SIM_PIN 6
#define RIL_REQUEST_CHANGE_SIM_PIN2 7
#define RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION 8
#define RIL_REQUEST_GET_CURRENT_CALLS 9
#define RIL_REQUEST_DIAL 10
#define RIL_REQUEST_GET_IMSI 11
#define RIL_REQUEST_HANGUP 12
#define RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND 13
#define RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND 14
#define RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE 15
#define RIL_REQUEST_CONFERENCE 16
#define RIL_REQUEST_UDUB 17
#define RIL_REQUEST_LAST_CALL_FAIL_CAUSE 18
#define RIL_REQUEST_SIGNAL_STRENGTH 19
#define RIL_REQUEST_VOICE_REGISTRATION_STATE 20
#define RIL_REQUEST_DATA_REGISTRATION_STATE 21
#define RIL_REQUEST_OPERATOR 22
#define RIL_REQUEST_RADIO_POWER 23
#define RIL_REQUEST_DTMF 24
#define RIL_REQUEST_SEND_SMS 25
#define RIL_REQUEST_SEND_SMS_EXPECT_MORE 26
#define RIL_REQUEST_SETUP_DATA_CALL 27
#define RIL_REQUEST_SIM_IO 28
#define RIL_REQUEST_SEND_USSD 29
#define RIL_REQUEST_CANCEL_USSD 30
#define RIL_REQUEST_GET_CLIR 31
#define RIL_REQUEST_SET_CLIR 32
#define RIL_REQUEST_QUERY_CALL_FORWARD_STATUS 33
#define RIL_REQUEST_SET_CALL_FORWARD 34
#define RIL_REQUEST_QUERY_CALL_WAITING 35
#define RIL_REQUEST_SET_CALL_WAITING 36
#define RIL_REQUEST_SMS_ACKNOWLEDGE 37
#define RIL_REQUEST_GET_IMEI 38
#define RIL_REQUEST_GET_IMEISV 39
#define RIL_REQUEST_ANSWER 40
#define RIL_REQUEST_DEACTIVATE_DATA_CALL 41
#define RIL_REQUEST_QUERY_FACILITY_LOCK 42
#define RIL_REQUEST_SET_FACILITY_LOCK 43
#define RIL_REQUEST_CHANGE_BARRING_PASSWORD 44
#define RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE 45
#define RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC 46
#define RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL 47
#define RIL_REQUEST_QUERY_AVAILABLE_NETWORKS 48
#define RIL_REQUEST_DTMF_START 49
#define RIL_REQUEST_DTMF_STOP 50
#define RIL_REQUEST_BASEBAND_VERSION 51
#define RIL_REQUEST_SEPARATE_CONNECTION 52
#define RIL_REQUEST_SET_MUTE 53
#define RIL_REQUEST_GET_MUTE 54
#define RIL_REQUEST_QUERY_CLIP 55
#define RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE 56
#define RIL_REQUEST_DATA_CALL_LIST 57
#define RIL_REQUEST_RESET_RADIO 58
#define RIL_REQUEST_OEM_HOOK_RAW 59
#define RIL_REQUEST_OEM_HOOK_STRINGS 60
#define RIL_REQUEST_SCREEN_STATE 61
#define RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION 62
#define RIL_REQUEST_WRITE_SMS_TO_SIM 63
#define RIL_REQUEST_DELETE_SMS_ON_SIM 64
#define RIL_REQUEST_SET_BAND_MODE 65
#define RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE 66
#define RIL_REQUEST_STK_GET_PROFILE 67
#define RIL_REQUEST_STK_SET_PROFILE 68
#define RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND 69
#define RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE 70
#define RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM 71
#define RIL_REQUEST_EXPLICIT_CALL_TRANSFER 72
#define RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE 73
#define RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE 74
#define RIL_REQUEST_GET_NEIGHBORING_CELL_IDS 75
#define RIL_REQUEST_SET_LOCATION_UPDATES 76
#define RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE 77
#define RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE 78
#define RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE 79
#define RIL_REQUEST_SET_TTY_MODE 80
#define RIL_REQUEST_QUERY_TTY_MODE 81
#define RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE 82
#define RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE 83
#define RIL_REQUEST_CDMA_FLASH 84
#define RIL_REQUEST_CDMA_BURST_DTMF 85
#define RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY 86
#define RIL_REQUEST_CDMA_SEND_SMS 87
#define RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE 88
#define RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG 89
#define RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG 90
#define RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION 91
#define RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG 92
#define RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG 93
#define RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION 94
#define RIL_REQUEST_CDMA_SUBSCRIPTION 95
#define RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM 96
#define RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM 97
#define RIL_REQUEST_DEVICE_IDENTITY 98
#define RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE 99
#define RIL_REQUEST_GET_SMSC_ADDRESS 100
#define RIL_REQUEST_SET_SMSC_ADDRESS 101
#define RIL_REQUEST_REPORT_SMS_MEMORY_STATUS 102
#define RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING 103
#define RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE 104
#define RIL_REQUEST_ISIM_AUTHENTICATION 105
#define RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU 106
#define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
#define RIL_REQUEST_VOICE_RADIO_TECH 108
#define RIL_REQUEST_GET_CELL_INFO_LIST 109
#define RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE 110
#define RIL_REQUEST_SET_INITIAL_ATTACH_APN 111
#define RIL_REQUEST_IMS_REGISTRATION_STATE 112
#define RIL_REQUEST_IMS_SEND_SMS 113
#define RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC 114
#define RIL_REQUEST_SIM_OPEN_CHANNEL 115
#define RIL_REQUEST_SIM_CLOSE_CHANNEL 116
#define RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL 117
#define RIL_REQUEST_NV_READ_ITEM 118
#define RIL_REQUEST_NV_WRITE_ITEM 119
#define RIL_REQUEST_NV_WRITE_CDMA_PRL 120
#define RIL_REQUEST_NV_RESET_CONFIG 121
/* SET_UICC_SUBSCRIPTION was 115 in v9 and 122 in v10 and later */
#define RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION 115
#define RIL_REQUEST_SET_UICC_SUBSCRIPTION 122
#define RIL_REQUEST_ALLOW_DATA 123
#define RIL_REQUEST_GET_HARDWARE_CONFIG 124
#define RIL_REQUEST_SIM_AUTHENTICATION 125
#define RIL_REQUEST_GET_DC_RT_INFO 126
#define RIL_REQUEST_SET_DC_RT_INFO_RATE 127
#define RIL_REQUEST_SET_DATA_PROFILE 128
#define RIL_REQUEST_SHUTDOWN 129
#define RIL_REQUEST_GET_RADIO_CAPABILITY 130
#define RIL_REQUEST_SET_RADIO_CAPABILITY 131
/* RIL Unsolicited Messages, rild -> ofono */
#define RIL_UNSOL_RESPONSE_BASE 1000
#define RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED 1000
#define RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 1001
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 1002
#define RIL_UNSOL_RESPONSE_NEW_SMS 1003
#define RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT 1004
#define RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM 1005
#define RIL_UNSOL_ON_USSD 1006
#define RIL_UNSOL_ON_USSD_REQUEST 1007
#define RIL_UNSOL_NITZ_TIME_RECEIVED 1008
#define RIL_UNSOL_SIGNAL_STRENGTH 1009
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 1010
#define RIL_UNSOL_SUPP_SVC_NOTIFICATION 1011
#define RIL_UNSOL_STK_SESSION_END 1012
#define RIL_UNSOL_STK_PROACTIVE_COMMAND 1013
#define RIL_UNSOL_STK_EVENT_NOTIFY 1014
#define RIL_UNSOL_STK_CALL_SETUP 1015
#define RIL_UNSOL_SIM_SMS_STORAGE_FULL 1016
#define RIL_UNSOL_SIM_REFRESH 1017
#define RIL_UNSOL_CALL_RING 1018
#define RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 1019
#define RIL_UNSOL_RESPONSE_CDMA_NEW_SMS 1020
#define RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS 1021
#define RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL 1022
#define RIL_UNSOL_RESTRICTED_STATE_CHANGED 1023
#define RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE 1024
#define RIL_UNSOL_CDMA_CALL_WAITING 1025
#define RIL_UNSOL_CDMA_OTA_PROVISION_STATUS 1026
#define RIL_UNSOL_CDMA_INFO_REC 1027
#define RIL_UNSOL_OEM_HOOK_RAW 1028
#define RIL_UNSOL_RINGBACK_TONE 1029
#define RIL_UNSOL_RESEND_INCALL_MUTE 1030
#define RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED 1031
#define RIL_UNSOL_CDMA_PRL_CHANGED 1032
#define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033
#define RIL_UNSOL_RIL_CONNECTED 1034
#define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035
#define RIL_UNSOL_CELL_INFO_LIST 1036
#define RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED 1037
#define RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED 1038
#define RIL_UNSOL_SRVCC_STATE_NOTIFY 1039
#define RIL_UNSOL_HARDWARE_CONFIG_CHANGED 1040
#define RIL_UNSOL_DC_RT_INFO_CHANGED 1041
#define RIL_UNSOL_RADIO_CAPABILITY 1042
#define RIL_UNSOL_ON_SS 1043
#define RIL_UNSOL_STK_CC_ALPHA_NOTIFY 1044
/* A special request, ofono -> rild */
#define RIL_RESPONSE_ACKNOWLEDGEMENT 800
#ifdef __cplusplus
}
#endif
#endif /* __OFONO_RIL_CONSTANTS_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,64 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __OFONO_RIL_TRANSPORT_H
#define __OFONO_RIL_TRANSPORT_H
#include <ofono/types.h>
#include <glib.h>
#ifdef __cplusplus
extern "C" {
#endif
struct grilio_transport;
/*
* The api_version field makes it possible to keep using old plugins
* even if struct ofono_ril_transport gets extended with new callbacks.
*/
#define OFONO_RIL_TRANSPORT_API_VERSION (0)
/*
* The connect callback takes a (char*) -> (char*) hashtable containing
* transport-specific connection parameters. The caller receives a reference
* i.e. it has to unref the returned object.
*/
struct ofono_ril_transport {
const char *name;
int api_version; /* OFONO_RIL_TRANSPORT_API_VERSION */
struct grilio_transport *(*connect)(GHashTable *params);
};
int ofono_ril_transport_register(const struct ofono_ril_transport *t);
void ofono_ril_transport_unregister(const struct ofono_ril_transport *t);
struct grilio_transport *ofono_ril_transport_connect(const char *name,
GHashTable *params);
#ifdef __cplusplus
}
#endif
#endif /* __OFONO_RIL_TRANSPORT_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -35,18 +35,6 @@ struct sailfish_cell_info;
typedef void (*sailfish_slot_manager_impl_cb_t) typedef void (*sailfish_slot_manager_impl_cb_t)
(struct sailfish_slot_manager_impl *impl, void *user_data); (struct sailfish_slot_manager_impl *impl, void *user_data);
enum sailfish_slot_flags {
SAILFISH_SLOT_NO_FLAGS = 0,
/* Normally we should be able to have two simultaneously active
* data contexts - one for mobile data and one for MMS. The flag
* below says that for whatever reason it's impossible and mobile
* data has to be disconnected before we can send or receive MMS.
* On such devices it may not be a good idea to automatically
* download MMS because that would kill active mobile data
* connections. */
SAILFISH_SLOT_SINGLE_CONTEXT = 0x01
};
typedef struct sailfish_slot { typedef struct sailfish_slot {
const char *path; const char *path;
const char *imei; const char *imei;
@@ -93,12 +81,6 @@ struct sailfish_slot *sailfish_manager_slot_add
const char *path, enum ofono_radio_access_mode techs, const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv, const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state); enum sailfish_sim_state sim_state);
struct sailfish_slot *sailfish_manager_slot_add2
(struct sailfish_slot_manager *m, struct sailfish_slot_impl *i,
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state,
enum sailfish_slot_flags flags);
void sailfish_manager_imei_obtained(struct sailfish_slot *s, const char *imei); void sailfish_manager_imei_obtained(struct sailfish_slot *s, const char *imei);
void sailfish_manager_imeisv_obtained(struct sailfish_slot *s, void sailfish_manager_imeisv_obtained(struct sailfish_slot *s,
const char *imeisv); const char *imeisv);

View File

@@ -56,7 +56,6 @@ enum ofono_error_type {
OFONO_ERROR_TYPE_CEER, OFONO_ERROR_TYPE_CEER,
OFONO_ERROR_TYPE_SIM, OFONO_ERROR_TYPE_SIM,
OFONO_ERROR_TYPE_FAILURE, OFONO_ERROR_TYPE_FAILURE,
OFONO_ERROR_TYPE_ERRNO
}; };
enum ofono_disconnect_reason { enum ofono_disconnect_reason {
@@ -71,6 +70,16 @@ struct ofono_error {
int error; int error;
}; };
#define OFONO_EINVAL(error) do { \
error->type = OFONO_ERROR_TYPE_FAILURE; \
error->error = -EINVAL; \
} while (0)
#define OFONO_NO_ERROR(error) do { \
error->type = OFONO_ERROR_TYPE_NO_ERROR; \
error->error = 0; \
} while (0)
#define OFONO_MAX_PHONE_NUMBER_LENGTH 80 #define OFONO_MAX_PHONE_NUMBER_LENGTH 80
#define OFONO_MAX_CALLER_NAME_LENGTH 80 #define OFONO_MAX_CALLER_NAME_LENGTH 80

View File

@@ -1,128 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __OFONO_VOICECALL_FILTER_H
#define __OFONO_VOICECALL_FILTER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ofono/voicecall.h>
/* 27.007 Section 7.6 */
enum ofono_clip_validity {
OFONO_CLIP_VALIDITY_VALID = 0,
OFONO_CLIP_VALIDITY_WITHHELD,
OFONO_CLIP_VALIDITY_NOT_AVAILABLE
};
/* 27.007 Section 7.18 */
enum ofono_call_status {
OFONO_CALL_STATUS_ACTIVE = 0,
OFONO_CALL_STATUS_HELD,
OFONO_CALL_STATUS_DIALING,
OFONO_CALL_STATUS_ALERTING,
OFONO_CALL_STATUS_INCOMING,
OFONO_CALL_STATUS_WAITING,
OFONO_CALL_STATUS_DISCONNECTED
};
/* 27.007 Section 7.18 */
enum ofono_call_direction {
OFONO_CALL_DIRECTION_MOBILE_ORIGINATED = 0,
OFONO_CALL_DIRECTION_MOBILE_TERMINATED
};
/* 27.007 Section 7.30 */
enum ofono_cnap_validity {
OFONO_CNAP_VALIDITY_VALID = 0,
OFONO_CNAP_VALIDITY_WITHHELD,
OFONO_CNAP_VALIDITY_NOT_AVAILABLE
};
enum ofono_voicecall_filter_dial_result {
OFONO_VOICECALL_FILTER_DIAL_CONTINUE, /* Run the next filter */
OFONO_VOICECALL_FILTER_DIAL_BLOCK /* Don't dial*/
};
enum ofono_voicecall_filter_incoming_result {
OFONO_VOICECALL_FILTER_INCOMING_CONTINUE, /* Run the next filter */
OFONO_VOICECALL_FILTER_INCOMING_HANGUP, /* Hangup incoming call */
OFONO_VOICECALL_FILTER_INCOMING_IGNORE /* Ignore incoming call */
};
typedef void (*ofono_voicecall_filter_dial_cb_t)
(enum ofono_voicecall_filter_dial_result result,
void *data);
typedef void (*ofono_voicecall_filter_incoming_cb_t)
(enum ofono_voicecall_filter_incoming_result result,
void *data);
#define OFONO_VOICECALL_FILTER_PRIORITY_LOW (-100)
#define OFONO_VOICECALL_FILTER_PRIORITY_DEFAULT (0)
#define OFONO_VOICECALL_FILTER_PRIORITY_HIGH (100)
/*
* The api_version field makes it possible to keep using old plugins
* even if struct ofono_voicecall_filter gets extended with new callbacks.
*/
#define OFONO_VOICECALL_FILTER_API_VERSION (0)
/*
* The filter callbacks either invoke the completion callback directly
* or return the id of the cancellable asynchronous operation (but never
* both). If non-zero value is returned, the completion callback has to
* be invoked later on a fresh stack. Once the asynchronous filtering
* operation is cancelled, the associated completion callback must not
* be invoked.
*
* Please avoid making blocking D-Bus calls from the filter callbacks.
*/
struct ofono_voicecall_filter {
const char *name;
int api_version; /* OFONO_VOICECALL_FILTER_API_VERSION */
int priority;
void (*filter_cancel)(unsigned int id);
unsigned int (*filter_dial)(struct ofono_voicecall *vc,
const struct ofono_phone_number *number,
enum ofono_clir_option clir,
ofono_voicecall_filter_dial_cb_t cb,
void *data);
unsigned int (*filter_incoming)(struct ofono_voicecall *vc,
const struct ofono_call *call,
ofono_voicecall_filter_incoming_cb_t cb,
void *data);
};
void ofono_voicecall_filter_notify(struct ofono_voicecall *vc);
int ofono_voicecall_filter_register(const struct ofono_voicecall_filter *f);
void ofono_voicecall_filter_unregister(const struct ofono_voicecall_filter *f);
#ifdef __cplusplus
}
#endif
#endif /* __OFONO_VOICECALL_FILTER_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -153,8 +153,6 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
*/ */
void ofono_voicecall_mpty_hint(struct ofono_voicecall *vc, unsigned int ids); void ofono_voicecall_mpty_hint(struct ofono_voicecall *vc, unsigned int ids);
struct ofono_modem *ofono_voicecall_get_modem(struct ofono_voicecall *vc);
int ofono_voicecall_driver_register(const struct ofono_voicecall_driver *d); int ofono_voicecall_driver_register(const struct ofono_voicecall_driver *d);
void ofono_voicecall_driver_unregister(const struct ofono_voicecall_driver *d); void ofono_voicecall_driver_unregister(const struct ofono_voicecall_driver *d);

View File

@@ -79,7 +79,7 @@ static const gchar *dun_record =
static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data) static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{ {
struct ofono_emulator *em = user_data; struct ofono_emulator *em = user_data;
GList *i; struct ofono_modem *modem;
int fd; int fd;
DBG(""); DBG("");
@@ -90,17 +90,16 @@ static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
return; return;
} }
DBG("Using all modems for emulator"); /* Pick the first powered modem */
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_DUN); em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
if (em == NULL) { if (em == NULL) {
g_io_channel_shutdown(io, TRUE, NULL); g_io_channel_shutdown(io, TRUE, NULL);
return; return;
} }
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
fd = g_io_channel_unix_get_fd(io); fd = g_io_channel_unix_get_fd(io);
g_io_channel_set_close_on_unref(io, FALSE); g_io_channel_set_close_on_unref(io, FALSE);

View File

@@ -56,7 +56,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
const char *device; const char *device;
int fd; int fd;
struct ofono_emulator *em; struct ofono_emulator *em;
GList *i; struct ofono_modem *modem;
DBG("Profile handler NewConnection"); DBG("Profile handler NewConnection");
@@ -80,6 +80,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
DBG("%s", device); DBG("%s", device);
/* Pick the first powered modem */
if (modems == NULL) { if (modems == NULL) {
close(fd); close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -87,9 +88,10 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"No GPRS capable modem"); "No GPRS capable modem");
} }
DBG("Using all modems for emulator."); modem = modems->data;
DBG("Picked modem %p for emulator", modem);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_DUN); em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
if (em == NULL) { if (em == NULL) {
close(fd); close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -97,9 +99,6 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"Not enough resources"); "Not enough resources");
} }
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
ofono_emulator_register(em, fd); ofono_emulator_register(em, fd);
return dbus_message_new_method_return(msg); return dbus_message_new_method_return(msg);

View File

@@ -91,7 +91,6 @@ static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
struct ofono_modem *modem; struct ofono_modem *modem;
struct ofono_emulator *em; struct ofono_emulator *em;
int fd; int fd;
GList *i;
DBG(""); DBG("");
@@ -100,18 +99,17 @@ static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
return; return;
} }
if (modems == NULL) /* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
return; return;
DBG("Using all modems for emulator"); DBG("Picked modem %p for emulator", modem);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_HFP); em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL) if (em == NULL)
return; return;
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
fd = g_io_channel_unix_get_fd(io); fd = g_io_channel_unix_get_fd(io);
g_io_channel_set_close_on_unref(io, FALSE); g_io_channel_set_close_on_unref(io, FALSE);

View File

@@ -47,18 +47,19 @@ typedef struct GAtResult GAtResult;
#include "bluez5.h" #include "bluez5.h"
#include "bluetooth.h" #include "bluetooth.h"
#ifndef DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD -1
#endif
#define HFP_AG_EXT_PROFILE_PATH "/bluetooth/profile/hfp_ag" #define HFP_AG_EXT_PROFILE_PATH "/bluetooth/profile/hfp_ag"
#define BT_ADDR_SIZE 18 #define BT_ADDR_SIZE 18
#define HFP_AG_DRIVER "hfp-ag-driver" #define HFP_AG_DRIVER "hfp-ag-driver"
static gboolean hfp_ag_enabled;
static guint service_watch_id;
static guint modemwatch_id; static guint modemwatch_id;
static GList *modems; static GList *modems;
static GHashTable *sim_hash = NULL; static GHashTable *sim_hash = NULL;
static GHashTable *connection_hash; static GHashTable *connection_hash;
static struct ofono_emulator *emulator = NULL;
static int hfp_card_probe(struct ofono_handsfree_card *card, static int hfp_card_probe(struct ofono_handsfree_card *card,
unsigned int vendor, void *data) unsigned int vendor, void *data)
@@ -71,8 +72,6 @@ static int hfp_card_probe(struct ofono_handsfree_card *card,
static void hfp_card_remove(struct ofono_handsfree_card *card) static void hfp_card_remove(struct ofono_handsfree_card *card)
{ {
DBG(""); DBG("");
emulator = NULL;
} }
static void codec_negotiation_done_cb(int err, void *data) static void codec_negotiation_done_cb(int err, void *data)
@@ -173,9 +172,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
struct sockaddr_rc saddr; struct sockaddr_rc saddr;
socklen_t optlen; socklen_t optlen;
struct ofono_emulator *em; struct ofono_emulator *em;
struct ofono_modem *modem;
char local[BT_ADDR_SIZE], remote[BT_ADDR_SIZE]; char local[BT_ADDR_SIZE], remote[BT_ADDR_SIZE];
struct ofono_handsfree_card *card; struct ofono_handsfree_card *card;
GList *i;
int err; int err;
DBG("Profile handler NewConnection"); DBG("Profile handler NewConnection");
@@ -203,6 +202,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
goto invalid; goto invalid;
} }
/* Pick the first voicecall capable modem */
if (modems == NULL) { if (modems == NULL) {
close(fd); close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -210,7 +210,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"No voice call capable modem"); "No voice call capable modem");
} }
DBG("Using all modems for emulator."); modem = modems->data;
DBG("Picked modem %p for emulator", modem);
memset(&saddr, 0, sizeof(saddr)); memset(&saddr, 0, sizeof(saddr));
optlen = sizeof(saddr); optlen = sizeof(saddr);
@@ -238,7 +240,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
bt_ba2str(&saddr.rc_bdaddr, remote); bt_ba2str(&saddr.rc_bdaddr, remote);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_HFP); em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
if (em == NULL) { if (em == NULL) {
close(fd); close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -246,10 +248,6 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"Not enough resources"); "Not enough resources");
} }
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
emulator = em;
ofono_emulator_register(em, fd); ofono_emulator_register(em, fd);
fd_dup = dup(fd); fd_dup = dup(fd);
@@ -369,9 +367,6 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data)
modems = g_list_append(modems, modem); modems = g_list_append(modems, modem);
if (emulator)
ofono_emulator_add_modem(emulator, modem);
if (modems->next != NULL) if (modems->next != NULL)
return; return;
@@ -464,27 +459,29 @@ static void call_modemwatch(struct ofono_modem *modem, void *user)
modem_watch(modem, TRUE, user); modem_watch(modem, TRUE, user);
} }
static void hfp_ag_enable(DBusConnection *conn) static int hfp_ag_init(void)
{ {
DBusConnection *conn = ofono_dbus_get_connection();
int err; int err;
if (DBUS_TYPE_UNIX_FD < 0)
return -EBADF;
/* Registers External Profile handler */ /* Registers External Profile handler */
if (!g_dbus_register_interface(conn, if (!g_dbus_register_interface(conn, HFP_AG_EXT_PROFILE_PATH,
HFP_AG_EXT_PROFILE_PATH, BLUEZ_PROFILE_INTERFACE,
BLUEZ_PROFILE_INTERFACE, profile_methods, NULL,
profile_methods, NULL, NULL, NULL)) {
NULL, NULL, NULL, NULL)) {
ofono_error("Register Profile interface failed: %s", ofono_error("Register Profile interface failed: %s",
HFP_AG_EXT_PROFILE_PATH); HFP_AG_EXT_PROFILE_PATH);
return; return -EIO;
} }
err = ofono_handsfree_card_driver_register(&hfp_ag_driver); err = ofono_handsfree_card_driver_register(&hfp_ag_driver);
if (err < 0) { if (err < 0) {
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH, g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE); BLUEZ_PROFILE_INTERFACE);
ofono_error("Failed to register driver: %d", err); return err;
return;
} }
sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal); sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -493,65 +490,10 @@ static void hfp_ag_enable(DBusConnection *conn)
__ofono_modem_foreach(call_modemwatch, NULL); __ofono_modem_foreach(call_modemwatch, NULL);
connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal, connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, connection_destroy); g_free, connection_destroy);
ofono_handsfree_audio_ref(); ofono_handsfree_audio_ref();
hfp_ag_enabled = TRUE;
}
static void hfp_ag_disable(DBusConnection *conn)
{
if (modemwatch_id) {
__ofono_modemwatch_remove(modemwatch_id);
modemwatch_id = 0;
}
if (connection_hash) {
g_hash_table_destroy(connection_hash);
connection_hash = NULL;
}
g_list_free(modems);
modems = NULL;
if (sim_hash) {
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash);
sim_hash = NULL;
}
if (hfp_ag_enabled) {
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
ofono_handsfree_audio_unref();
}
hfp_ag_enabled = FALSE;
}
static void bluez_connect_cb(DBusConnection *connection, void *user_data)
{
hfp_ag_enable(connection);
}
static void bluez_disconnect_cb(DBusConnection *connection, void *user_data)
{
hfp_ag_disable(connection);
}
static int hfp_ag_init(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
hfp_ag_enable(conn);
service_watch_id = g_dbus_add_service_watch(conn, "org.bluez",
bluez_connect_cb,
bluez_disconnect_cb,
NULL, NULL);
return 0; return 0;
} }
@@ -559,12 +501,19 @@ static void hfp_ag_exit(void)
{ {
DBusConnection *conn = ofono_dbus_get_connection(); DBusConnection *conn = ofono_dbus_get_connection();
if (service_watch_id) { __ofono_modemwatch_remove(modemwatch_id);
g_dbus_remove_watch(conn, service_watch_id); g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
service_watch_id = 0; BLUEZ_PROFILE_INTERFACE);
}
hfp_ag_disable(conn); ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
g_hash_table_destroy(connection_hash);
g_list_free(modems);
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash);
ofono_handsfree_audio_unref();
} }
OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins", OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins",

View File

@@ -89,7 +89,6 @@ struct sailfish_slot_priv {
struct sailfish_cell_info *cellinfo; struct sailfish_cell_info *cellinfo;
struct sailfish_cell_info_dbus *cellinfo_dbus; struct sailfish_cell_info_dbus *cellinfo_dbus;
enum sailfish_sim_state sim_state; enum sailfish_sim_state sim_state;
enum sailfish_slot_flags flags;
gulong watch_event_id[WATCH_EVENT_COUNT]; gulong watch_event_id[WATCH_EVENT_COUNT];
char *imei; char *imei;
char *imeisv; char *imeisv;
@@ -321,17 +320,6 @@ struct sailfish_slot *sailfish_manager_slot_add
const char *path, enum ofono_radio_access_mode techs, const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv, const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state) enum sailfish_sim_state sim_state)
{
return sailfish_manager_slot_add2(m, impl, path, techs, imei, imeisv,
sim_state, SAILFISH_SLOT_NO_FLAGS);
}
struct sailfish_slot *sailfish_manager_slot_add2
(struct sailfish_slot_manager *m, struct sailfish_slot_impl *impl,
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state,
enum sailfish_slot_flags flags)
{ {
/* Only accept these calls when we are starting! We have been /* Only accept these calls when we are starting! We have been
* assuming all along that the number of slots is known right * assuming all along that the number of slots is known right
@@ -351,7 +339,6 @@ struct sailfish_slot *sailfish_manager_slot_add2
s->impl = impl; s->impl = impl;
s->manager = m; s->manager = m;
s->sim_state = sim_state; s->sim_state = sim_state;
s->flags = flags;
s->watch = sailfish_watch_new(path); s->watch = sailfish_watch_new(path);
s->siminfo = sailfish_sim_info_new(path); s->siminfo = sailfish_sim_info_new(path);
s->siminfo_dbus = sailfish_sim_info_dbus_new(s->siminfo); s->siminfo_dbus = sailfish_sim_info_dbus_new(s->siminfo);
@@ -662,12 +649,10 @@ static int sailfish_manager_update_modem_paths(struct sailfish_manager_priv *p)
mms_slot = sailfish_manager_find_slot_imsi(p, p->mms_imsi); mms_slot = sailfish_manager_find_slot_imsi(p, p->mms_imsi);
} }
if (mms_slot && (mms_slot != slot || if (mms_slot && mms_slot != slot) {
(slot->flags & SAILFISH_SLOT_SINGLE_CONTEXT))) {
/* /*
* Reset default data SIM if * Reset default data SIM if another SIM is
* a) another SIM is temporarily selected for MMS; or * temporarily selected for MMS.
* b) this slot can't have more than one context active.
*/ */
slot = NULL; slot = NULL;
} }

View File

@@ -24,7 +24,6 @@
#endif #endif
#include <glib.h> #include <glib.h>
#include <errno.h>
#include <gdbus.h> #include <gdbus.h>
#include "ofono.h" #include "ofono.h"
@@ -38,7 +37,7 @@ struct error_mapping_entry {
DBusMessage *(*ofono_error_func)(DBusMessage *); DBusMessage *(*ofono_error_func)(DBusMessage *);
}; };
static const struct error_mapping_entry cme_errors_mapping[] = { struct error_mapping_entry cme_errors_mapping[] = {
{ 3, __ofono_error_not_allowed }, { 3, __ofono_error_not_allowed },
{ 4, __ofono_error_not_supported }, { 4, __ofono_error_not_supported },
{ 16, __ofono_error_incorrect_password }, { 16, __ofono_error_incorrect_password },
@@ -46,16 +45,6 @@ static const struct error_mapping_entry cme_errors_mapping[] = {
{ 31, __ofono_error_timed_out }, { 31, __ofono_error_timed_out },
{ 32, __ofono_error_access_denied }, { 32, __ofono_error_access_denied },
{ 50, __ofono_error_invalid_args }, { 50, __ofono_error_invalid_args },
{ }
};
static const struct error_mapping_entry errno_errors_mapping[] = {
{ EACCES, __ofono_error_access_denied },
{ EOPNOTSUPP, __ofono_error_not_supported },
{ ENOSYS, __ofono_error_not_implemented },
{ ETIMEDOUT, __ofono_error_timed_out },
{ EINPROGRESS, __ofono_error_busy },
{ }
}; };
static void append_variant(DBusMessageIter *iter, static void append_variant(DBusMessageIter *iter,
@@ -430,31 +419,26 @@ DBusMessage *__ofono_error_network_terminated(DBusMessage *msg)
" network"); " network");
} }
static DBusMessage *__ofono_map_error(const struct error_mapping_entry *map,
int error, DBusMessage *msg)
{
const struct error_mapping_entry *e;
for (e = map; e->ofono_error_func; e++)
if (e->error == error)
return e->ofono_error_func(msg);
return __ofono_error_failed(msg);
}
DBusMessage *__ofono_error_from_error(const struct ofono_error *error, DBusMessage *__ofono_error_from_error(const struct ofono_error *error,
DBusMessage *msg) DBusMessage *msg)
{ {
struct error_mapping_entry *e;
int maxentries;
int i;
switch (error->type) { switch (error->type) {
case OFONO_ERROR_TYPE_CME: case OFONO_ERROR_TYPE_CME:
return __ofono_map_error(cme_errors_mapping, error->error, msg); e = cme_errors_mapping;
maxentries = sizeof(cme_errors_mapping) /
sizeof(struct error_mapping_entry);
for (i = 0; i < maxentries; i++)
if (e[i].error == error->error)
return e[i].ofono_error_func(msg);
break;
case OFONO_ERROR_TYPE_CMS: case OFONO_ERROR_TYPE_CMS:
return __ofono_error_failed(msg); return __ofono_error_failed(msg);
case OFONO_ERROR_TYPE_CEER: case OFONO_ERROR_TYPE_CEER:
return __ofono_error_failed(msg); return __ofono_error_failed(msg);
case OFONO_ERROR_TYPE_ERRNO:
return __ofono_map_error(errno_errors_mapping,
ABS(error->error), msg);
default: default:
return __ofono_error_failed(msg); return __ofono_error_failed(msg);
} }

View File

@@ -51,9 +51,7 @@ struct hfp_codec_info {
}; };
struct ofono_emulator { struct ofono_emulator {
GList *atoms; struct ofono_atom *atom;
GList *registered_atoms;
gboolean emulator_registered;
enum ofono_emulator_type type; enum ofono_emulator_type type;
GAtServer *server; GAtServer *server;
GAtPPP *ppp; GAtPPP *ppp;
@@ -357,17 +355,10 @@ static struct indicator *find_indicator(struct ofono_emulator *em,
static struct ofono_call *find_call_with_status(struct ofono_emulator *em, static struct ofono_call *find_call_with_status(struct ofono_emulator *em,
int status) int status)
{ {
struct ofono_modem *modem; struct ofono_modem *modem = __ofono_atom_get_modem(em->atom);
struct ofono_voicecall *vc = NULL; struct ofono_voicecall *vc;
GList *i;
for (i = em->atoms; i; i = i->next) {
modem = __ofono_atom_get_modem(i->data);
if ((vc = __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem)))
break;
}
vc = __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem);
if (vc == NULL) if (vc == NULL)
return NULL; return NULL;
@@ -1162,20 +1153,7 @@ static void emulator_unregister(struct ofono_atom *atom)
struct ofono_emulator *em = __ofono_atom_get_data(atom); struct ofono_emulator *em = __ofono_atom_get_data(atom);
GSList *l; GSList *l;
DBG("%p (atom %p)", em, atom); DBG("%p", em);
em->registered_atoms = g_list_remove(em->registered_atoms, atom);
if (em->registered_atoms)
return;
if (!em->emulator_registered) {
DBG("emulator already unregistered");
return;
}
em->emulator_registered = FALSE;
DBG("%p no more atoms registered", em);
if (em->callsetup_source) { if (em->callsetup_source) {
g_source_remove(em->callsetup_source); g_source_remove(em->callsetup_source);
@@ -1207,27 +1185,12 @@ static void emulator_unregister(struct ofono_atom *atom)
em->card = NULL; em->card = NULL;
} }
static void emulator_register_atom(struct ofono_emulator *em, struct ofono_atom *atom)
{
if (!g_list_find(em->registered_atoms, atom)) {
em->registered_atoms = g_list_append(em->registered_atoms, atom);
DBG("%p", atom);
__ofono_atom_register(atom, emulator_unregister);
}
}
void ofono_emulator_register(struct ofono_emulator *em, int fd) void ofono_emulator_register(struct ofono_emulator *em, int fd)
{ {
GIOChannel *io; GIOChannel *io;
GList *i;
DBG("%p, %d", em, fd); DBG("%p, %d", em, fd);
if (em->emulator_registered) {
DBG("emulator already registered");
return;
}
if (fd < 0) if (fd < 0)
return; return;
@@ -1277,8 +1240,7 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
g_at_server_register(em->server, "+BCS", bcs_cb, em, NULL); g_at_server_register(em->server, "+BCS", bcs_cb, em, NULL);
} }
for (i = em->atoms; i; i = i->next) __ofono_atom_register(em->atom, emulator_unregister);
emulator_register_atom(em, i->data);
switch (em->type) { switch (em->type) {
case OFONO_EMULATOR_TYPE_DUN: case OFONO_EMULATOR_TYPE_DUN:
@@ -1292,41 +1254,31 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
default: default:
break; break;
} }
em->emulator_registered = TRUE;
}
static void emulator_free(struct ofono_emulator *em)
{
g_assert(!em->atoms);
DBG("free emulator %p", em);
if (em->registered_atoms)
g_list_free(em->registered_atoms);
g_free(em);
} }
static void emulator_remove(struct ofono_atom *atom) static void emulator_remove(struct ofono_atom *atom)
{ {
struct ofono_emulator *em = __ofono_atom_get_data(atom); struct ofono_emulator *em = __ofono_atom_get_data(atom);
DBG("remove atom %p", atom); DBG("atom: %p", atom);
em->atoms = g_list_remove(em->atoms, atom);
if (!em->atoms) g_free(em);
emulator_free(em);
} }
struct ofono_emulator *ofono_emulator_create(enum ofono_emulator_type type) struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
enum ofono_emulator_type type)
{ {
struct ofono_emulator *em; struct ofono_emulator *em;
enum ofono_atom_type atom_t;
if (type != OFONO_EMULATOR_TYPE_DUN && type != OFONO_EMULATOR_TYPE_HFP) { DBG("modem: %p, type: %d", modem, type);
DBG("unsupported emulator type %d", type);
if (type == OFONO_EMULATOR_TYPE_DUN)
atom_t = OFONO_ATOM_TYPE_EMULATOR_DUN;
else if (type == OFONO_EMULATOR_TYPE_HFP)
atom_t = OFONO_ATOM_TYPE_EMULATOR_HFP;
else
return NULL; return NULL;
}
DBG("create emulator of type %d", type);
em = g_try_new0(struct ofono_emulator, 1); em = g_try_new0(struct ofono_emulator, 1);
@@ -1344,59 +1296,15 @@ struct ofono_emulator *ofono_emulator_create(enum ofono_emulator_type type)
em->events_mode = 3; /* default mode is forwarding events */ em->events_mode = 3; /* default mode is forwarding events */
em->cmee_mode = 0; /* CME ERROR disabled by default */ em->cmee_mode = 0; /* CME ERROR disabled by default */
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
return em; return em;
} }
void ofono_emulator_add_modem(struct ofono_emulator *em,
struct ofono_modem *modem)
{
struct ofono_atom *atom;
enum ofono_atom_type atom_t;
if (em->type == OFONO_EMULATOR_TYPE_DUN)
atom_t = OFONO_ATOM_TYPE_EMULATOR_DUN;
else
atom_t = OFONO_ATOM_TYPE_EMULATOR_HFP;
if ((atom = __ofono_modem_find_atom(modem, atom_t))) {
if (g_list_find(em->atoms, atom)) {
DBG("modem %p already added", modem);
goto register_atom;
}
}
DBG("%p", modem);
atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
em->atoms = g_list_append(em->atoms, atom);
register_atom:
if (em->emulator_registered)
emulator_register_atom(em, atom);
}
void ofono_emulator_remove(struct ofono_emulator *em) void ofono_emulator_remove(struct ofono_emulator *em)
{ {
GList *remove_list; __ofono_atom_free(em->atom);
GList *i;
DBG("");
/* If emulator has atoms we make a copy of the atom list here,
* as the list is modified when the atoms are being destroyed.
* When last atom is gone struct ofono_emulator is freed as
* well (in emulator_remove()). */
if (em->atoms) {
remove_list = g_list_copy(em->atoms);
for (i = remove_list; i; i = i->next) {
DBG("free atom %p", i->data);
__ofono_atom_free(i->data);
}
g_list_free(remove_list);
} else {
emulator_free(em);
}
} }
void ofono_emulator_send_final(struct ofono_emulator *em, void ofono_emulator_send_final(struct ofono_emulator *em,
@@ -1439,7 +1347,6 @@ void ofono_emulator_send_final(struct ofono_emulator *em,
case OFONO_ERROR_TYPE_CEER: case OFONO_ERROR_TYPE_CEER:
case OFONO_ERROR_TYPE_SIM: case OFONO_ERROR_TYPE_SIM:
case OFONO_ERROR_TYPE_FAILURE: case OFONO_ERROR_TYPE_FAILURE:
case OFONO_ERROR_TYPE_ERRNO:
failure: failure:
g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR); g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
break; break;

View File

@@ -18,65 +18,57 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
struct gprs_filter_request;
struct gprs_filter_request_fn {
const char *name;
gboolean (*can_process)(const struct ofono_gprs_filter *filter);
guint (*process)(const struct ofono_gprs_filter *filter,
struct gprs_filter_request *req);
void (*complete)(struct gprs_filter_request *req, gboolean allow);
void (*free)(struct gprs_filter_request *req);
};
struct gprs_filter_request { struct gprs_filter_request {
int refcount;
struct gprs_filter_chain *chain; struct gprs_filter_chain *chain;
struct ofono_gprs_context *gc;
const struct gprs_filter_request_fn *fn;
GSList *filter_link; GSList *filter_link;
guint pending_id; guint pending_id;
guint next_id; guint next_id;
struct ofono_gprs_primary_context ctx;
gprs_filter_activate_cb_t act;
ofono_destroy_func destroy; ofono_destroy_func destroy;
void* user_data; void* user_data;
}; };
struct gprs_filter_request_activate { /* There's no need to support more than one request at a time */
struct gprs_filter_request req;
struct ofono_gprs_primary_context ctx;
gprs_filter_activate_cb_t cb;
};
struct gprs_filter_request_check {
struct gprs_filter_request req;
ofono_gprs_filter_check_cb_t cb;
};
struct gprs_filter_chain { struct gprs_filter_chain {
struct ofono_gprs *gprs; struct ofono_gprs_context *gc;
GSList *req_list; struct gprs_filter_request *req;
}; };
static GSList *gprs_filter_list = NULL; static GSList *gprs_filter_list = NULL;
static void gprs_filter_request_init(struct gprs_filter_request *req, static void gprs_filter_request_process(struct gprs_filter_request *req);
const struct gprs_filter_request_fn *fn,
struct gprs_filter_chain *chain, struct ofono_gprs_context *gc, static void gprs_filter_copy_context(struct ofono_gprs_primary_context *dest,
ofono_destroy_func destroy, void *user_data) const struct ofono_gprs_primary_context *src)
{ {
dest->cid = src->cid;
dest->proto = src->proto;
dest->auth_method = src->auth_method;
strncpy(dest->apn, src->apn, OFONO_GPRS_MAX_APN_LENGTH);
strncpy(dest->username, src->username, OFONO_GPRS_MAX_USERNAME_LENGTH);
strncpy(dest->password, src->password, OFONO_GPRS_MAX_PASSWORD_LENGTH);
dest->apn[OFONO_GPRS_MAX_APN_LENGTH] = 0;
dest->username[OFONO_GPRS_MAX_USERNAME_LENGTH] = 0;
dest->password[OFONO_GPRS_MAX_PASSWORD_LENGTH] = 0;
}
static struct gprs_filter_request *gprs_filter_request_new
(struct gprs_filter_chain *chain,
const struct ofono_gprs_primary_context *ctx,
gprs_filter_activate_cb_t act,
ofono_destroy_func destroy, void *user_data)
{
struct gprs_filter_request *req = g_new0(struct gprs_filter_request, 1);
req->chain = chain; req->chain = chain;
req->fn = fn;
req->gc = gc;
req->filter_link = gprs_filter_list; req->filter_link = gprs_filter_list;
gprs_filter_copy_context(&req->ctx, ctx);
req->act = act;
req->destroy = destroy; req->destroy = destroy;
req->user_data = user_data; req->user_data = user_data;
return req;
/*
* The list holds an implicit reference to the message. The reference
* is released by gprs_filter_request_free when the message is removed
* from the list.
*/
req->refcount = 1;
chain->req_list = g_slist_append(chain->req_list, req);
} }
static void gprs_filter_request_cancel(struct gprs_filter_request *req) static void gprs_filter_request_cancel(struct gprs_filter_request *req)
@@ -97,94 +89,21 @@ static void gprs_filter_request_cancel(struct gprs_filter_request *req)
} }
} }
static void gprs_filter_request_dispose(struct gprs_filter_request *req)
{
/* May be invoked several times per request */
if (req->destroy) {
ofono_destroy_func destroy = req->destroy;
req->destroy = NULL;
destroy(req->user_data);
}
}
static void gprs_filter_request_free(struct gprs_filter_request *req) static void gprs_filter_request_free(struct gprs_filter_request *req)
{ {
gprs_filter_request_dispose(req); if (req->destroy) {
req->fn->free(req); req->destroy(req->user_data);
}
#define gprs_filter_request_ref(req) ((req)->refcount++, req)
static int gprs_filter_request_unref(struct gprs_filter_request *req)
{
const int refcount = --(req->refcount);
if (!refcount) {
gprs_filter_request_free(req);
}
return refcount;
}
static void gprs_filter_request_free1(gpointer data)
{
struct gprs_filter_request *req = data;
/*
* This is a g_slist_free_full() callback for use by
* __ofono_gprs_filter_chain_free(), meaning that the
* chain is no more. Zero the pointer to it in case if
* this is not the last reference.
*/
req->chain = NULL;
gprs_filter_request_unref(req);
}
static void gprs_filter_request_dequeue(struct gprs_filter_request *req)
{
struct gprs_filter_chain *chain = req->chain;
GSList *l;
/*
* Single-linked list is not particularly good at searching
* and removing the elements but since it should be pretty
* short (typically just one request), it's not worth optimization.
*/
if (chain && (l = g_slist_find(chain->req_list, req)) != NULL) {
gprs_filter_request_free1(l->data);
chain->req_list = g_slist_delete_link(chain->req_list, l);
} }
g_free(req);
} }
static void gprs_filter_request_complete(struct gprs_filter_request *req, static void gprs_filter_request_complete(struct gprs_filter_request *req,
gboolean allow) gboolean allow)
{ {
gprs_filter_request_ref(req); req->chain->req = NULL;
req->fn->complete(req, allow); gprs_filter_request_cancel(req);
gprs_filter_request_dispose(req); req->act(allow ? &req->ctx : NULL, req->user_data);
gprs_filter_request_dequeue(req); gprs_filter_request_free(req);
gprs_filter_request_unref(req);
}
static void gprs_filter_request_process(struct gprs_filter_request *req)
{
GSList *l = req->filter_link;
const struct ofono_gprs_filter *f = l->data;
const struct gprs_filter_request_fn *fn = req->fn;
while (f && !fn->can_process(f)) {
l = l->next;
f = l ? l->data : NULL;
}
gprs_filter_request_ref(req);
if (f) {
req->filter_link = l;
req->pending_id = fn->process(f, req);
} else {
gprs_filter_request_complete(req, TRUE);
}
gprs_filter_request_unref(req);
} }
static void gprs_filter_request_next(struct gprs_filter_request *req, static void gprs_filter_request_next(struct gprs_filter_request *req,
@@ -194,7 +113,7 @@ static void gprs_filter_request_next(struct gprs_filter_request *req,
req->next_id = g_idle_add(fn, req); req->next_id = g_idle_add(fn, req);
} }
static gboolean gprs_filter_request_continue_cb(gpointer data) static gboolean gprs_filter_continue_cb(gpointer data)
{ {
struct gprs_filter_request *req = data; struct gprs_filter_request *req = data;
@@ -208,7 +127,7 @@ static gboolean gprs_filter_request_continue_cb(gpointer data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static gboolean gprs_filter_request_disallow_cb(gpointer data) static gboolean gprs_filter_cancel_cb(gpointer data)
{ {
struct gprs_filter_request *req = data; struct gprs_filter_request *req = data;
@@ -217,185 +136,91 @@ static gboolean gprs_filter_request_disallow_cb(gpointer data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
/*==========================================================================* static void gprs_filter_activate_cb
* gprs_filter_request_activate
*==========================================================================*/
static void gprs_filter_copy_context(struct ofono_gprs_primary_context *dest,
const struct ofono_gprs_primary_context *src)
{
dest->cid = src->cid;
dest->proto = src->proto;
dest->auth_method = src->auth_method;
strncpy(dest->apn, src->apn, OFONO_GPRS_MAX_APN_LENGTH);
strncpy(dest->username, src->username, OFONO_GPRS_MAX_USERNAME_LENGTH);
strncpy(dest->password, src->password, OFONO_GPRS_MAX_PASSWORD_LENGTH);
dest->apn[OFONO_GPRS_MAX_APN_LENGTH] = 0;
dest->username[OFONO_GPRS_MAX_USERNAME_LENGTH] = 0;
dest->password[OFONO_GPRS_MAX_PASSWORD_LENGTH] = 0;
}
static struct gprs_filter_request_activate *gprs_filter_request_activate_cast
(struct gprs_filter_request *req)
{
return (struct gprs_filter_request_activate *)req;
}
static gboolean gprs_filter_request_activate_can_process
(const struct ofono_gprs_filter *f)
{
return f->filter_activate != NULL;
}
static void gprs_filter_request_activate_cb
(const struct ofono_gprs_primary_context *ctx, void *data) (const struct ofono_gprs_primary_context *ctx, void *data)
{ {
struct gprs_filter_request_activate *act = data; struct gprs_filter_request *req = data;
struct gprs_filter_request *req = &act->req;
const struct ofono_gprs_filter *filter = req->filter_link->data; const struct ofono_gprs_filter *filter = req->filter_link->data;
if (ctx) { if (ctx) {
if (ctx != &act->ctx) { if (ctx != &req->ctx) {
/* The filter may have updated context settings */ /* The filter may have updated context settings */
gprs_filter_copy_context(&act->ctx, ctx); gprs_filter_copy_context(&req->ctx, ctx);
} }
gprs_filter_request_next(req, gprs_filter_request_continue_cb); gprs_filter_request_next(req, gprs_filter_continue_cb);
} else { } else {
DBG("%s not allowing to activate mobile data", filter->name); DBG("%s not allowing to activate mobile data", filter->name);
gprs_filter_request_next(req, gprs_filter_request_disallow_cb); gprs_filter_request_next(req, gprs_filter_cancel_cb);
} }
} }
static guint gprs_filter_request_activate_process static void gprs_filter_request_process(struct gprs_filter_request *req)
(const struct ofono_gprs_filter *f,
struct gprs_filter_request *req)
{ {
struct gprs_filter_request_activate *act = GSList *l = req->filter_link;
gprs_filter_request_activate_cast(req); const struct ofono_gprs_filter *f = l->data;
return f->filter_activate(req->gc, &act->ctx, while (f && !f->filter_activate) {
gprs_filter_request_activate_cb, act); l = l->next;
} f = l ? l->data : NULL;
}
static void gprs_filter_request_activate_complete if (f) {
(struct gprs_filter_request *req, gboolean allow) guint id;
{
struct gprs_filter_request_activate *act =
gprs_filter_request_activate_cast(req);
act->cb(allow ? &act->ctx : NULL, req->user_data); req->filter_link = l;
} id = f->filter_activate(req->chain->gc, &req->ctx,
gprs_filter_activate_cb, req);
static void gprs_filter_request_activate_free(struct gprs_filter_request *req) if (id) {
{ /*
g_slice_free1(sizeof(struct gprs_filter_request_activate), req); * If f->filter_activate returns zero, the request
} * may have already been deallocated. It's only
* guaranteed to be alive if f->filter_activate
static struct gprs_filter_request *gprs_filter_request_activate_new * returns non-zero id.
(struct gprs_filter_chain *chain, struct ofono_gprs_context *gc, */
const struct ofono_gprs_primary_context *ctx, req->pending_id = id;
gprs_filter_activate_cb_t cb, ofono_destroy_func destroy, }
void *data)
{
static const struct gprs_filter_request_fn activate_fn = {
.name = "activate",
.can_process = gprs_filter_request_activate_can_process,
.process = gprs_filter_request_activate_process,
.complete = gprs_filter_request_activate_complete,
.free = gprs_filter_request_activate_free
};
struct gprs_filter_request_activate *act =
g_slice_new0(struct gprs_filter_request_activate);
struct gprs_filter_request *req = &act->req;
gprs_filter_request_init(req, &activate_fn, chain, gc, destroy, data);
gprs_filter_copy_context(&act->ctx, ctx);
act->cb = cb;
return req;
}
/*==========================================================================*
* gprs_filter_request_check
*==========================================================================*/
static struct gprs_filter_request_check *gprs_filter_request_check_cast
(struct gprs_filter_request *req)
{
return (struct gprs_filter_request_check *)req;
}
static gboolean gprs_filter_request_check_can_process
(const struct ofono_gprs_filter *f)
{
return f->api_version >= 1 && f->filter_check != NULL;
}
static void gprs_filter_request_check_cb(ofono_bool_t allow, void *data)
{
struct gprs_filter_request_check *check = data;
struct gprs_filter_request *req = &check->req;
const struct ofono_gprs_filter *filter = req->filter_link->data;
if (allow) {
gprs_filter_request_next(req, gprs_filter_request_continue_cb);
} else { } else {
DBG("%s not allowing mobile data", filter->name); gprs_filter_request_complete(req, TRUE);
gprs_filter_request_next(req, gprs_filter_request_disallow_cb);
} }
} }
static guint gprs_filter_request_check_process void __ofono_gprs_filter_chain_activate(struct gprs_filter_chain *chain,
(const struct ofono_gprs_filter *f, const struct ofono_gprs_primary_context *ctx,
struct gprs_filter_request *req) gprs_filter_activate_cb_t act, ofono_destroy_func destroy,
void *user_data)
{ {
return f->filter_check(req->chain->gprs, gprs_filter_request_check_cb, if (chain && gprs_filter_list && ctx && act) {
gprs_filter_request_check_cast(req)); if (!chain->req) {
chain->req = gprs_filter_request_new(chain, ctx,
act, destroy, user_data);
gprs_filter_request_process(chain->req);
return;
} else {
/*
* This shouldn't be happening - ofono core
* makes sure that the next context activation
* request is not submitted until the previous
* has completed.
*/
ctx = NULL;
}
}
if (act) {
act(ctx, user_data);
}
if (destroy) {
destroy(user_data);
}
} }
static void gprs_filter_request_check_complete struct gprs_filter_chain *__ofono_gprs_filter_chain_new
(struct gprs_filter_request *req, gboolean allow) (struct ofono_gprs_context *gc)
{
gprs_filter_request_check_cast(req)->cb(allow, req->user_data);
}
static void gprs_filter_request_check_free(struct gprs_filter_request *req)
{
g_slice_free1(sizeof(struct gprs_filter_request_check), req);
}
static struct gprs_filter_request *gprs_filter_request_check_new
(struct gprs_filter_chain *chain, gprs_filter_check_cb_t cb,
ofono_destroy_func destroy, void *data)
{
static const struct gprs_filter_request_fn check_fn = {
.name = "check",
.can_process = gprs_filter_request_check_can_process,
.process = gprs_filter_request_check_process,
.complete = gprs_filter_request_check_complete,
.free = gprs_filter_request_check_free
};
struct gprs_filter_request_check *check =
g_slice_new0(struct gprs_filter_request_check);
struct gprs_filter_request *req = &check->req;
gprs_filter_request_init(req, &check_fn, chain, NULL, destroy, data);
check->cb = cb;
return req;
}
/*==========================================================================*
* gprs_filter_chain
*==========================================================================*/
struct gprs_filter_chain *__ofono_gprs_filter_chain_new(struct ofono_gprs *gp)
{ {
struct gprs_filter_chain *chain = NULL; struct gprs_filter_chain *chain = NULL;
if (gp) { if (gc) {
chain = g_new0(struct gprs_filter_chain, 1); chain = g_new0(struct gprs_filter_chain, 1);
chain->gprs = gp; chain->gc = gc;
} }
return chain; return chain;
} }
@@ -403,100 +228,22 @@ struct gprs_filter_chain *__ofono_gprs_filter_chain_new(struct ofono_gprs *gp)
void __ofono_gprs_filter_chain_free(struct gprs_filter_chain *chain) void __ofono_gprs_filter_chain_free(struct gprs_filter_chain *chain)
{ {
if (chain) { if (chain) {
__ofono_gprs_filter_chain_cancel(chain, NULL); if (chain->req) {
gprs_filter_request_complete(chain->req, TRUE);
}
g_free(chain); g_free(chain);
} }
} }
void __ofono_gprs_filter_chain_cancel(struct gprs_filter_chain *chain, void __ofono_gprs_filter_chain_cancel(struct gprs_filter_chain *chain)
struct ofono_gprs_context *gc)
{ {
if (chain) { if (chain && chain->req) {
GSList *l, *canceled; gprs_filter_request_cancel(chain->req);
gprs_filter_request_free(chain->req);
/* Move canceled requests to a separate list */ chain->req = NULL;
if (gc) {
GSList *prev = NULL;
canceled = NULL;
l = chain->req_list;
while (l) {
GSList *next = l->next;
struct gprs_filter_request *req = l->data;
if (req->gc == gc) {
/* This one will get canceled */
l->next = canceled;
canceled = l;
if (prev) {
prev->next = next;
} else {
chain->req_list = next;
}
} else {
/* This one survives */
prev = l;
}
l = next;
}
} else {
/* Everything is getting canceled */
canceled = chain->req_list;
chain->req_list = NULL;
}
/* Actually cancel each request */
for (l = canceled; l; l = l->next) {
gprs_filter_request_cancel(l->data);
}
/* And deallocate them */
g_slist_free_full(canceled, gprs_filter_request_free1);
} }
} }
void __ofono_gprs_filter_chain_activate(struct gprs_filter_chain *chain,
struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx,
gprs_filter_activate_cb_t cb, ofono_destroy_func destroy,
void *user_data)
{
if (chain && gprs_filter_list && ctx && cb) {
gprs_filter_request_process
(gprs_filter_request_activate_new(chain, gc, ctx,
cb, destroy, user_data));
} else {
if (cb) {
cb(ctx, user_data);
}
if (destroy) {
destroy(user_data);
}
}
}
void __ofono_gprs_filter_chain_check(struct gprs_filter_chain *chain,
gprs_filter_check_cb_t cb, ofono_destroy_func destroy,
void *user_data)
{
if (chain && gprs_filter_list && cb) {
gprs_filter_request_process
(gprs_filter_request_check_new(chain, cb, destroy,
user_data));
} else {
if (cb) {
cb(TRUE, user_data);
}
if (destroy) {
destroy(user_data);
}
}
}
/*==========================================================================*
* ofono_gprs_filter
*==========================================================================*/
/** /**
* Returns 0 if both are equal; * Returns 0 if both are equal;
* <0 if a comes before b; * <0 if a comes before b;

View File

@@ -85,7 +85,6 @@ struct ofono_gprs {
void *driver_data; void *driver_data;
struct ofono_atom *atom; struct ofono_atom *atom;
unsigned int spn_watch; unsigned int spn_watch;
struct gprs_filter_chain *filters;
}; };
struct ipv4_settings { struct ipv4_settings {
@@ -118,6 +117,7 @@ struct ofono_gprs_context {
void *driver_data; void *driver_data;
struct context_settings *settings; struct context_settings *settings;
struct ofono_atom *atom; struct ofono_atom *atom;
struct gprs_filter_chain *filters;
}; };
struct pri_context { struct pri_context {
@@ -137,13 +137,7 @@ struct pri_context {
struct ofono_gprs *gprs; struct ofono_gprs *gprs;
}; };
/* static void gprs_attached_update(struct ofono_gprs *gprs);
* In Sailfish OS fork gprs_attached_update() is exported to plugins
* as ofono_gprs_attached_update(). Exported functions must start
* with ofono_ prefix.
*/
#define gprs_attached_update(gprs) ofono_gprs_attached_update(gprs)
static void gprs_netreg_update(struct ofono_gprs *gprs); static void gprs_netreg_update(struct ofono_gprs *gprs);
static void gprs_deactivate_next(struct ofono_gprs *gprs); static void gprs_deactivate_next(struct ofono_gprs *gprs);
static void write_context_settings(struct ofono_gprs *gprs, static void write_context_settings(struct ofono_gprs *gprs,
@@ -375,9 +369,7 @@ static void release_context(struct pri_context *ctx)
if (ctx == NULL || ctx->gprs == NULL || ctx->context_driver == NULL) if (ctx == NULL || ctx->gprs == NULL || ctx->context_driver == NULL)
return; return;
__ofono_gprs_filter_chain_cancel(ctx->gprs->filters, __ofono_gprs_filter_chain_cancel(ctx->context_driver->filters);
ctx->context_driver);
gprs_cid_release(ctx->gprs, ctx->context.cid); gprs_cid_release(ctx->gprs, ctx->context.cid);
ctx->context.cid = 0; ctx->context.cid = 0;
ctx->context_driver->inuse = FALSE; ctx->context_driver->inuse = FALSE;
@@ -1057,17 +1049,16 @@ static DBusMessage *pri_provision_context(DBusConnection *conn,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
const struct ofono_gprs_provision_data *ap = settings + i; const struct ofono_gprs_provision_data *ap = settings + i;
if (ap->type == ctx->type && ap_valid(ap)) { if (ap->type == ctx->type && ap_valid(ap)) {
if (ctx->pending || ctx->gprs->pending) { if ((!ctx->active &&
/* Context is being messed with */ !ctx->pending && !ctx->gprs->pending) ||
reply = __ofono_error_busy(msg); !pri_deactivation_required(ctx, ap)) {
} else if (ctx->active &&
pri_deactivation_required(ctx, ap)) {
/* Context needs to be deactivated first */
reply = __ofono_error_busy(msg);
} else {
/* Re-provision the context */ /* Re-provision the context */
pri_reset_context_properties(ctx, ap); pri_reset_context_properties(ctx, ap);
reply = dbus_message_new_method_return(msg); reply = dbus_message_new_method_return(msg);
} else {
/* Context should be inactive */
if (ctx->gprs->pending || ctx->pending)
reply = __ofono_error_busy(msg);
} }
break; break;
} }
@@ -1557,40 +1548,11 @@ static DBusMessage *pri_set_auth_method(struct pri_context *ctx,
return NULL; return NULL;
} }
struct pri_request_data { static void gprs_context_activate(const struct ofono_gprs_primary_context *ctx,
struct pri_context *pri; void *data)
DBusMessage *msg;
};
static struct pri_request_data *pri_request_new(struct pri_context *pri)
{ {
struct pri_request_data *data = g_new0(struct pri_request_data, 1); struct pri_context *pri = data;
data->pri = pri;
data->msg = pri->pending;
return data;
}
static void pri_request_free(void *user_data)
{
struct pri_request_data *data = user_data;
struct pri_context *pri = data->pri;
if (pri->pending && pri->pending == data->msg) {
__ofono_dbus_pending_reply(&pri->pending,
__ofono_error_canceled(pri->pending));
}
g_free(data);
}
static void pri_activate_filt(const struct ofono_gprs_primary_context *ctx,
void *user_data)
{
struct pri_request_data *data = user_data;
struct pri_context *pri = data->pri;
data->msg = NULL;
if (ctx) { if (ctx) {
struct ofono_gprs_context *gc = pri->context_driver; struct ofono_gprs_context *gc = pri->context_driver;
@@ -1657,9 +1619,9 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
ctx->pending = dbus_message_ref(msg); ctx->pending = dbus_message_ref(msg);
if (value) if (value)
__ofono_gprs_filter_chain_activate(gc->gprs->filters, __ofono_gprs_filter_chain_activate(gc->filters,
gc, &ctx->context, pri_activate_filt, &ctx->context, gprs_context_activate,
pri_request_free, pri_request_new(ctx)); NULL, ctx);
else else
gc->driver->deactivate_primary(gc, ctx->context.cid, gc->driver->deactivate_primary(gc, ctx->context.cid,
pri_deactivate_callback, ctx); pri_deactivate_callback, ctx);
@@ -1943,8 +1905,14 @@ static void release_active_contexts(struct ofono_gprs *gprs)
} }
} }
static void gprs_set_attached(struct ofono_gprs *gprs, ofono_bool_t attached) static void gprs_attached_update(struct ofono_gprs *gprs)
{ {
ofono_bool_t attached;
attached = gprs->driver_attached &&
(gprs->status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
gprs->status == NETWORK_REGISTRATION_STATUS_ROAMING);
if (attached == gprs->attached) if (attached == gprs->attached)
return; return;
@@ -1971,32 +1939,6 @@ static void gprs_set_attached(struct ofono_gprs *gprs, ofono_bool_t attached)
gprs_set_attached_property(gprs, attached); gprs_set_attached_property(gprs, attached);
} }
static void gprs_attached_check_cb(ofono_bool_t allow, void *user_data)
{
gprs_set_attached((struct ofono_gprs *)user_data, allow);
}
void gprs_attached_update(struct ofono_gprs *gprs)
{
ofono_bool_t attached = gprs->driver_attached &&
(gprs->status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
gprs->status == NETWORK_REGISTRATION_STATUS_ROAMING);
if (!attached) {
/* Cancel all other checks - nothing is allowed if we are
* not attached */
__ofono_gprs_filter_chain_cancel(gprs->filters, NULL);
/* We are done synchronously */
gprs_set_attached(gprs, FALSE);
} else {
/* This implicitely cancels the previous check if it's still
* running, so that we never have two simultanous checks. */
__ofono_gprs_filter_chain_check(gprs->filters,
gprs_attached_check_cb, NULL, gprs);
}
}
static void registration_status_cb(const struct ofono_error *error, static void registration_status_cb(const struct ofono_error *error,
int status, void *data) int status, void *data)
{ {
@@ -3152,9 +3094,7 @@ static void gprs_context_remove(struct ofono_atom *atom)
if (gc->driver && gc->driver->remove) if (gc->driver && gc->driver->remove)
gc->driver->remove(gc); gc->driver->remove(gc);
if (gc->gprs) __ofono_gprs_filter_chain_free(gc->filters);
__ofono_gprs_filter_chain_cancel(gc->gprs->filters, gc);
g_free(gc); g_free(gc);
} }
@@ -3186,6 +3126,7 @@ struct ofono_gprs_context *ofono_gprs_context_create(struct ofono_modem *modem,
if (drv->probe(gc, vendor, data) < 0) if (drv->probe(gc, vendor, data) < 0)
continue; continue;
gc->filters = __ofono_gprs_filter_chain_new(gc);
gc->driver = drv; gc->driver = drv;
break; break;
} }
@@ -3470,7 +3411,6 @@ static void gprs_remove(struct ofono_atom *atom)
if (gprs->driver && gprs->driver->remove) if (gprs->driver && gprs->driver->remove)
gprs->driver->remove(gprs); gprs->driver->remove(gprs);
__ofono_gprs_filter_chain_free(gprs->filters);
g_free(gprs); g_free(gprs);
} }
@@ -3507,7 +3447,6 @@ struct ofono_gprs *ofono_gprs_create(struct ofono_modem *modem,
gprs->status = NETWORK_REGISTRATION_STATUS_UNKNOWN; gprs->status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
gprs->netreg_status = NETWORK_REGISTRATION_STATUS_UNKNOWN; gprs->netreg_status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
gprs->pid_map = idmap_new(MAX_CONTEXTS); gprs->pid_map = idmap_new(MAX_CONTEXTS);
gprs->filters = __ofono_gprs_filter_chain_new(gprs);
return gprs; return gprs;
} }

View File

@@ -912,7 +912,6 @@ void ofono_handsfree_audio_unref(void)
if (agent) { if (agent) {
agent_release(agent); agent_release(agent);
agent_free(agent); agent_free(agent);
agent = NULL;
} }
__ofono_handsfree_audio_manager_cleanup(); __ofono_handsfree_audio_manager_cleanup();

View File

@@ -190,16 +190,6 @@ struct ofono_sim *ofono_modem_get_sim(struct ofono_modem *modem)
return __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem); return __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
} }
struct ofono_gprs *ofono_modem_get_gprs(struct ofono_modem *modem)
{
return __ofono_atom_find(OFONO_ATOM_TYPE_GPRS, modem);
}
struct ofono_voicecall *ofono_modem_get_voicecall(struct ofono_modem *modem)
{
return __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem);
}
struct ofono_atom *__ofono_modem_add_atom(struct ofono_modem *modem, struct ofono_atom *__ofono_modem_add_atom(struct ofono_modem *modem,
enum ofono_atom_type type, enum ofono_atom_type type,
void (*destruct)(struct ofono_atom *), void (*destruct)(struct ofono_atom *),

View File

@@ -596,44 +596,15 @@ struct gprs_filter_chain;
typedef void (*gprs_filter_activate_cb_t) typedef void (*gprs_filter_activate_cb_t)
(const struct ofono_gprs_primary_context *ctx, void *user_data); (const struct ofono_gprs_primary_context *ctx, void *user_data);
typedef void (*gprs_filter_check_cb_t)(ofono_bool_t allow, void *user_data); struct gprs_filter_chain *__ofono_gprs_filter_chain_new
struct gprs_filter_chain *__ofono_gprs_filter_chain_new(struct ofono_gprs *gp); (struct ofono_gprs_context *gc);
void __ofono_gprs_filter_chain_free(struct gprs_filter_chain *chain); void __ofono_gprs_filter_chain_free(struct gprs_filter_chain *chain);
void __ofono_gprs_filter_chain_cancel(struct gprs_filter_chain *chain, void __ofono_gprs_filter_chain_cancel(struct gprs_filter_chain *chain);
struct ofono_gprs_context *gc);
void __ofono_gprs_filter_chain_activate(struct gprs_filter_chain *chain, void __ofono_gprs_filter_chain_activate(struct gprs_filter_chain *chain,
struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx, const struct ofono_gprs_primary_context *ctx,
gprs_filter_activate_cb_t act, ofono_destroy_func destroy, gprs_filter_activate_cb_t act, ofono_destroy_func destroy,
void *user_data); void *user_data);
void __ofono_gprs_filter_chain_check(struct gprs_filter_chain *chain,
gprs_filter_check_cb_t cb, ofono_destroy_func destroy,
void *user_data);
#include <ofono/voicecall-filter.h>
struct voicecall_filter_chain;
struct voicecall_filter_chain *__ofono_voicecall_filter_chain_new
(struct ofono_voicecall *vc);
void __ofono_voicecall_filter_chain_cancel(struct voicecall_filter_chain *c,
const struct ofono_call *call);
void __ofono_voicecall_filter_chain_restart(struct voicecall_filter_chain *c,
const struct ofono_call *call);
void __ofono_voicecall_filter_chain_free(struct voicecall_filter_chain *c);
void __ofono_voicecall_filter_chain_dial(struct voicecall_filter_chain *c,
const struct ofono_phone_number *number,
enum ofono_clir_option clir,
ofono_voicecall_filter_dial_cb_t cb,
ofono_destroy_func destroy, void *user_data);
void __ofono_voicecall_filter_chain_dial_check(struct voicecall_filter_chain *c,
const struct ofono_call *call,
ofono_voicecall_filter_dial_cb_t cb,
ofono_destroy_func destroy, void *user_data);
void __ofono_voicecall_filter_chain_incoming(struct voicecall_filter_chain *c,
const struct ofono_call *call,
ofono_voicecall_filter_incoming_cb_t cb,
ofono_destroy_func destroy, void *user_data);
#include <ofono/sim-mnclength.h> #include <ofono/sim-mnclength.h>

View File

@@ -211,26 +211,17 @@ void __ofono_plugin_cleanup(void)
DBG(""); DBG("");
/*
* Terminate the plugins but don't unload the libraries yet.
* Plugins may reference data structures allocated by each other.
*/
for (list = plugins; list; list = list->next) { for (list = plugins; list; list = list->next) {
struct ofono_plugin *plugin = list->data; struct ofono_plugin *plugin = list->data;
if (plugin->active == TRUE && plugin->desc->exit) if (plugin->active == TRUE && plugin->desc->exit)
plugin->desc->exit(); plugin->desc->exit();
}
/* Second pass - unload the libraries */
for (list = plugins; list; list = list->next) {
struct ofono_plugin *plugin = list->data;
if (plugin->handle) if (plugin->handle)
dlclose(plugin->handle); dlclose(plugin->handle);
g_free(plugin);
} }
/* Finally, free the memory */ g_slist_free(plugins);
g_slist_free_full(plugins, g_free);
plugins = NULL;
} }

View File

@@ -1,78 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <ofono/ril-transport.h>
#include <ofono/log.h>
#include <string.h>
#include <errno.h>
static GSList *ril_transports = NULL;
struct grilio_transport *ofono_ril_transport_connect(const char *name,
GHashTable *params)
{
if (name) {
GSList *l;
for (l = ril_transports; l; l = l->next) {
const struct ofono_ril_transport *t = l->data;
if (!strcmp(name, t->name)) {
return t->connect ? t->connect(params) : NULL;
}
}
ofono_error("Unknown RIL transport: %s", name);
}
return NULL;
}
int ofono_ril_transport_register(const struct ofono_ril_transport *t)
{
if (!t || !t->name) {
return -EINVAL;
} else {
GSList *l;
for (l = ril_transports; l; l = l->next) {
const struct ofono_ril_transport *t1 = l->data;
if (!strcmp(t->name, t1->name)) {
DBG("%s already registered", t->name);
return -EALREADY;
}
}
DBG("%s", t->name);
ril_transports = g_slist_append(ril_transports, (void*)t);
return 0;
}
}
void ofono_ril_transport_unregister(const struct ofono_ril_transport *t)
{
if (t && t->name) {
DBG("%s", t->name);
ril_transports = g_slist_remove(ril_transports, t);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -813,22 +813,6 @@ static void ussd_unregister(struct ofono_atom *atom)
DBusConnection *conn = ofono_dbus_get_connection(); DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_modem *modem = __ofono_atom_get_modem(atom); struct ofono_modem *modem = __ofono_atom_get_modem(atom);
const char *path = __ofono_atom_get_path(atom); const char *path = __ofono_atom_get_path(atom);
DBusMessage *reply;
if (ussd->pending) {
reply = __ofono_error_canceled(ussd->pending);
__ofono_dbus_pending_reply(&ussd->pending, reply);
}
if (ussd->cancel) {
reply = dbus_message_new_method_return(ussd->cancel);
__ofono_dbus_pending_reply(&ussd->cancel, reply);
}
if (ussd->req)
ussd_request_finish(ussd, -ECANCELED, 0, NULL, 0);
ussd_change_state(ussd, USSD_STATE_IDLE);
g_slist_free_full(ussd->ss_control_list, ssc_entry_destroy); g_slist_free_full(ussd->ss_control_list, ssc_entry_destroy);
ussd->ss_control_list = NULL; ussd->ss_control_list = NULL;

View File

@@ -1,662 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ofono.h"
#include "common.h"
#include <errno.h>
#include <string.h>
struct voicecall_filter_request;
struct voicecall_filter_request_fn {
const char *name;
gboolean (*can_process)(const struct ofono_voicecall_filter *filter);
guint (*process)(const struct ofono_voicecall_filter *filter,
struct voicecall_filter_request *req);
void (*allow)(struct voicecall_filter_request *req);
void (*free)(struct voicecall_filter_request *req);
};
struct voicecall_filter_request {
int refcount;
const struct voicecall_filter_request_fn *fn;
const struct ofono_call *call;
struct voicecall_filter_chain *chain;
GSList *filter_link;
guint pending_id;
guint next_id;
ofono_destroy_func destroy;
void* user_data;
};
struct voicecall_filter_request_dial {
struct voicecall_filter_request req;
const struct ofono_phone_number *number;
enum ofono_clir_option clir;
ofono_voicecall_filter_dial_cb_t cb;
};
struct voicecall_filter_request_incoming {
struct voicecall_filter_request req;
ofono_voicecall_filter_incoming_cb_t cb;
};
struct voicecall_filter_chain {
struct ofono_voicecall *vc;
GSList *req_list;
};
static GSList *voicecall_filters = NULL;
static void voicecall_filter_request_init(struct voicecall_filter_request *req,
const struct voicecall_filter_request_fn *fn,
struct voicecall_filter_chain *chain, const struct ofono_call *call,
ofono_destroy_func destroy, void *user_data)
{
req->fn = fn;
req->chain = chain;
req->call = call;
req->filter_link = voicecall_filters;
req->destroy = destroy;
req->user_data = user_data;
/*
* The list holds an implicit reference to the message. The reference
* is released by voicecall_filter_request_free when the message is
* removed from the list.
*/
req->refcount = 1;
chain->req_list = g_slist_append(chain->req_list, req);
}
static void voicecall_filter_request_cancel
(struct voicecall_filter_request *req)
{
if (req->pending_id) {
const struct ofono_voicecall_filter *f = req->filter_link->data;
/*
* If the filter returns id of the pending operation,
* then it must provide the cancel callback
*/
f->filter_cancel(req->pending_id);
req->pending_id = 0;
}
if (req->next_id) {
g_source_remove(req->next_id);
req->next_id = 0;
}
}
static void voicecall_filter_request_dispose
(struct voicecall_filter_request *req)
{
/* May be invoked several times per request */
if (req->destroy) {
ofono_destroy_func destroy = req->destroy;
req->destroy = NULL;
destroy(req->user_data);
}
}
static void voicecall_filter_request_free(struct voicecall_filter_request *req)
{
voicecall_filter_request_dispose(req);
req->fn->free(req);
}
#define voicecall_filter_request_ref(req) ((req)->refcount++, req)
static int voicecall_filter_request_unref(struct voicecall_filter_request *req)
{
const int refcount = --(req->refcount);
if (!refcount) {
voicecall_filter_request_free(req);
}
return refcount;
}
static void voicecall_filter_request_done(struct voicecall_filter_request *req)
{
/* Zero the pointer to it in case if this is not the last reference. */
req->chain = NULL;
voicecall_filter_request_unref(req);
}
static void voicecall_filter_request_dequeue
(struct voicecall_filter_request *req)
{
struct voicecall_filter_chain *chain = req->chain;
GSList *l;
/*
* Single-linked list is not particularly good at searching
* and removing the elements but since it should be pretty
* short (typically just one request), it's not worth optimization.
*/
if (chain && (l = g_slist_find(chain->req_list, req)) != NULL) {
voicecall_filter_request_done(l->data);
chain->req_list = g_slist_delete_link(chain->req_list, l);
}
}
static void voicecall_filter_request_complete
(struct voicecall_filter_request *req,
void (*complete)(struct voicecall_filter_request *req))
{
voicecall_filter_request_ref(req);
complete(req);
voicecall_filter_request_dispose(req);
voicecall_filter_request_dequeue(req);
voicecall_filter_request_unref(req);
}
static void voicecall_filter_request_process
(struct voicecall_filter_request *req)
{
GSList *l = req->filter_link;
const struct ofono_voicecall_filter *f = l->data;
const struct voicecall_filter_request_fn *fn = req->fn;
while (f && !fn->can_process(f)) {
l = l->next;
f = l ? l->data : NULL;
}
voicecall_filter_request_ref(req);
if (f) {
req->filter_link = l;
req->pending_id = fn->process(f, req);
} else {
voicecall_filter_request_complete(req, fn->allow);
}
voicecall_filter_request_unref(req);
}
static void voicecall_filter_request_next(struct voicecall_filter_request *req,
GSourceFunc fn)
{
req->pending_id = 0;
req->next_id = g_idle_add(fn, req);
}
static gboolean voicecall_filter_request_continue_cb(gpointer data)
{
struct voicecall_filter_request *req = data;
req->next_id = 0;
req->filter_link = req->filter_link->next;
if (req->filter_link) {
voicecall_filter_request_process(req);
} else {
voicecall_filter_request_complete(req, req->fn->allow);
}
return G_SOURCE_REMOVE;
}
/*==========================================================================*
* voicecall_filter_request_dial
*==========================================================================*/
static struct voicecall_filter_request_dial *
voicecall_filter_request_dial_cast
(struct voicecall_filter_request *req)
{
return (struct voicecall_filter_request_dial *)req;
}
static void voicecall_filter_request_dial_block_complete_cb
(struct voicecall_filter_request *req)
{
struct voicecall_filter_request_dial *dial =
voicecall_filter_request_dial_cast(req);
dial->cb(OFONO_VOICECALL_FILTER_DIAL_BLOCK, req->user_data);
}
static gboolean voicecall_filter_request_dial_block_cb(gpointer data)
{
struct voicecall_filter_request_dial *dial = data;
struct voicecall_filter_request *req = &dial->req;
req->next_id = 0;
voicecall_filter_request_complete(req,
voicecall_filter_request_dial_block_complete_cb);
return G_SOURCE_REMOVE;
}
static void voicecall_filter_request_dial_cb
(enum ofono_voicecall_filter_dial_result result, void *data)
{
struct voicecall_filter_request_dial *dial = data;
struct voicecall_filter_request *req = &dial->req;
const struct ofono_voicecall_filter *filter = req->filter_link->data;
GSourceFunc next_cb;
if (result == OFONO_VOICECALL_FILTER_DIAL_BLOCK) {
ofono_info("%s is refusing to dial %s", filter->name,
phone_number_to_string(dial->number));
next_cb = voicecall_filter_request_dial_block_cb;
} else {
/* OFONO_VOICECALL_FILTER_DIAL_CONTINUE */
DBG("%s is ok with dialing %s", filter->name,
phone_number_to_string(dial->number));
next_cb = voicecall_filter_request_continue_cb;
}
voicecall_filter_request_next(req, next_cb);
}
static gboolean voicecall_filter_request_dial_can_process
(const struct ofono_voicecall_filter *f)
{
return f->filter_dial != NULL;
}
static guint voicecall_filter_request_dial_process
(const struct ofono_voicecall_filter *f,
struct voicecall_filter_request *req)
{
struct voicecall_filter_request_dial *dial =
voicecall_filter_request_dial_cast(req);
return f->filter_dial(req->chain->vc, dial->number, dial->clir,
voicecall_filter_request_dial_cb, dial);
}
static void voicecall_filter_request_dial_allow
(struct voicecall_filter_request *req)
{
struct voicecall_filter_request_dial *dial =
voicecall_filter_request_dial_cast(req);
dial->cb(OFONO_VOICECALL_FILTER_DIAL_CONTINUE, req->user_data);
}
static void voicecall_filter_request_dial_free
(struct voicecall_filter_request *req)
{
g_slice_free1(sizeof(struct voicecall_filter_request_dial), req);
}
static struct voicecall_filter_request *voicecall_filter_request_dial_new
(struct voicecall_filter_chain *chain,
const struct ofono_phone_number *number,
enum ofono_clir_option clir,
ofono_voicecall_filter_dial_cb_t cb,
ofono_destroy_func destroy, void *data)
{
static const struct voicecall_filter_request_fn fn = {
.name = "dial",
.can_process = voicecall_filter_request_dial_can_process,
.process = voicecall_filter_request_dial_process,
.allow = voicecall_filter_request_dial_allow,
.free = voicecall_filter_request_dial_free
};
struct voicecall_filter_request_dial *dial =
g_slice_new0(struct voicecall_filter_request_dial);
struct voicecall_filter_request *req = &dial->req;
voicecall_filter_request_init(req, &fn, chain, NULL, destroy, data);
dial->number = number;
dial->clir = clir;
dial->cb = cb;
return req;
}
/*==========================================================================*
* voicecall_filter_request_incoming
*==========================================================================*/
static struct voicecall_filter_request_incoming *
voicecall_filter_request_incoming_cast
(struct voicecall_filter_request *req)
{
return (struct voicecall_filter_request_incoming *)req;
}
static void voicecall_filter_request_incoming_hangup_complete_cb
(struct voicecall_filter_request *req)
{
struct voicecall_filter_request_incoming *in =
voicecall_filter_request_incoming_cast(req);
in->cb(OFONO_VOICECALL_FILTER_INCOMING_HANGUP, req->user_data);
}
static gboolean voicecall_filter_request_incoming_hangup_cb(gpointer data)
{
struct voicecall_filter_request_incoming *in = data;
struct voicecall_filter_request *req = &in->req;
req->next_id = 0;
voicecall_filter_request_complete(req,
voicecall_filter_request_incoming_hangup_complete_cb);
return G_SOURCE_REMOVE;
}
static void voicecall_filter_request_incoming_ignore_complete_cb
(struct voicecall_filter_request *req)
{
struct voicecall_filter_request_incoming *in =
voicecall_filter_request_incoming_cast(req);
in->cb(OFONO_VOICECALL_FILTER_INCOMING_IGNORE, req->user_data);
}
static gboolean voicecall_filter_request_incoming_ignore_cb(gpointer data)
{
struct voicecall_filter_request_incoming *in = data;
struct voicecall_filter_request *req = &in->req;
req->next_id = 0;
voicecall_filter_request_complete(req,
voicecall_filter_request_incoming_ignore_complete_cb);
return G_SOURCE_REMOVE;
}
static void voicecall_filter_request_incoming_cb
(enum ofono_voicecall_filter_incoming_result result, void *data)
{
struct voicecall_filter_request_incoming *in = data;
struct voicecall_filter_request *req = &in->req;
const struct ofono_voicecall_filter *filter = req->filter_link->data;
GSourceFunc next_cb;
if (result == OFONO_VOICECALL_FILTER_INCOMING_HANGUP) {
ofono_info("%s hangs up incoming call from %s", filter->name,
phone_number_to_string(&req->call->phone_number));
next_cb = voicecall_filter_request_incoming_hangup_cb;
} else if (result == OFONO_VOICECALL_FILTER_INCOMING_IGNORE) {
ofono_info("%s ignores incoming call from %s", filter->name,
phone_number_to_string(&req->call->phone_number));
next_cb = voicecall_filter_request_incoming_ignore_cb;
} else {
/* OFONO_VOICECALL_FILTER_INCOMING_CONTINUE */
DBG("%s is ok with accepting %s", filter->name,
phone_number_to_string(&req->call->phone_number));
next_cb = voicecall_filter_request_continue_cb;
}
voicecall_filter_request_next(req, next_cb);
}
static gboolean voicecall_filter_request_incoming_can_process
(const struct ofono_voicecall_filter *f)
{
return f->filter_incoming != NULL;
}
static guint voicecall_filter_request_incoming_process
(const struct ofono_voicecall_filter *f,
struct voicecall_filter_request *req)
{
return f->filter_incoming(req->chain->vc, req->call,
voicecall_filter_request_incoming_cb,
voicecall_filter_request_incoming_cast(req));
}
static void voicecall_filter_request_incoming_allow
(struct voicecall_filter_request *req)
{
struct voicecall_filter_request_incoming *in =
voicecall_filter_request_incoming_cast(req);
in->cb(OFONO_VOICECALL_FILTER_INCOMING_CONTINUE, req->user_data);
}
static void voicecall_filter_request_incoming_free
(struct voicecall_filter_request *req)
{
g_slice_free1(sizeof(struct voicecall_filter_request_incoming), req);
}
static struct voicecall_filter_request *voicecall_filter_request_incoming_new
(struct voicecall_filter_chain *chain, const struct ofono_call *call,
ofono_voicecall_filter_incoming_cb_t cb,
ofono_destroy_func destroy, void *data)
{
static const struct voicecall_filter_request_fn fn = {
.name = "incoming",
.can_process = voicecall_filter_request_incoming_can_process,
.process = voicecall_filter_request_incoming_process,
.allow = voicecall_filter_request_incoming_allow,
.free = voicecall_filter_request_incoming_free
};
struct voicecall_filter_request_incoming *in =
g_slice_new0(struct voicecall_filter_request_incoming);
struct voicecall_filter_request *req = &in->req;
voicecall_filter_request_init(req, &fn, chain, call, destroy, data);
in->cb = cb;
return req;
}
/*==========================================================================*
* voicecall_filter_chain
*==========================================================================*/
struct voicecall_filter_chain *__ofono_voicecall_filter_chain_new
(struct ofono_voicecall *vc)
{
struct voicecall_filter_chain *chain = NULL;
if (vc) {
chain = g_new0(struct voicecall_filter_chain, 1);
chain->vc = vc;
}
return chain;
}
void __ofono_voicecall_filter_chain_free(struct voicecall_filter_chain *chain)
{
if (chain) {
__ofono_voicecall_filter_chain_cancel(chain, NULL);
g_free(chain);
}
}
static GSList *voicecall_filter_chain_select(struct voicecall_filter_chain *c,
const struct ofono_call *call)
{
if (c) {
GSList *selected;
/* Move selected requests to a separate list */
if (call) {
GSList *prev = NULL;
GSList *l = c->req_list;
selected = NULL;
while (l) {
GSList *next = l->next;
struct voicecall_filter_request *req = l->data;
if (req->call == call) {
/* This one will get canceled */
l->next = selected;
selected = l;
if (prev) {
prev->next = next;
} else {
c->req_list = next;
}
} else {
/* This one survives */
prev = l;
}
l = next;
}
} else {
/* Select everything */
selected = c->req_list;
c->req_list = NULL;
}
return selected;
} else {
return NULL;
}
}
void __ofono_voicecall_filter_chain_restart(struct voicecall_filter_chain *c,
const struct ofono_call *call)
{
GSList *l, *canceled = voicecall_filter_chain_select(c, call);
/* Cancel and resubmit each request */
for (l = canceled; l; l = l->next) {
struct voicecall_filter_request *req = l->data;
voicecall_filter_request_cancel(req);
voicecall_filter_request_process(req);
}
}
void __ofono_voicecall_filter_chain_cancel(struct voicecall_filter_chain *c,
const struct ofono_call *call)
{
GSList *l, *canceled = voicecall_filter_chain_select(c, call);
/* Cancel and deallocate each request */
for (l = canceled; l; l = l->next) {
struct voicecall_filter_request *req = l->data;
voicecall_filter_request_cancel(req);
voicecall_filter_request_done(req);
}
}
void __ofono_voicecall_filter_chain_dial(struct voicecall_filter_chain *chain,
const struct ofono_phone_number *number,
enum ofono_clir_option clir,
ofono_voicecall_filter_dial_cb_t cb,
ofono_destroy_func destroy, void *user_data)
{
if (chain && voicecall_filters && number && cb) {
voicecall_filter_request_process
(voicecall_filter_request_dial_new(chain, number,
clir, cb, destroy, user_data));
} else {
if (cb) {
cb(OFONO_VOICECALL_FILTER_DIAL_CONTINUE, user_data);
}
if (destroy) {
destroy(user_data);
}
}
}
void __ofono_voicecall_filter_chain_dial_check(struct voicecall_filter_chain *c,
const struct ofono_call *call,
ofono_voicecall_filter_dial_cb_t cb,
ofono_destroy_func destroy, void *user_data)
{
if (c && voicecall_filters && call && cb) {
struct voicecall_filter_request *req =
voicecall_filter_request_dial_new(c,
&call->phone_number, OFONO_CLIR_OPTION_DEFAULT,
cb, destroy, user_data);
req->call = call;
voicecall_filter_request_process(req);
} else {
if (cb) {
cb(OFONO_VOICECALL_FILTER_DIAL_CONTINUE, user_data);
}
if (destroy) {
destroy(user_data);
}
}
}
void __ofono_voicecall_filter_chain_incoming(struct voicecall_filter_chain *fc,
const struct ofono_call *call,
ofono_voicecall_filter_incoming_cb_t cb,
ofono_destroy_func destroy, void *user_data)
{
if (fc && voicecall_filters && call && cb) {
voicecall_filter_request_process
(voicecall_filter_request_incoming_new(fc, call,
cb, destroy, user_data));
} else {
if (cb) {
cb(OFONO_VOICECALL_FILTER_INCOMING_CONTINUE, user_data);
}
if (destroy) {
destroy(user_data);
}
}
}
/*==========================================================================*
* ofono_voicecall_filter
*==========================================================================*/
/**
* Returns 0 if both are equal;
* <0 if a comes before b;
* >0 if a comes after b.
*/
static gint voicecall_filter_sort(gconstpointer a, gconstpointer b)
{
const struct ofono_voicecall_filter *a_filter = a;
const struct ofono_voicecall_filter *b_filter = b;
if (a_filter->priority > b_filter->priority) {
/* a comes before b */
return -1;
} else if (a_filter->priority < b_filter->priority) {
/* a comes after b */
return 1;
} else {
/* Whatever, as long as the sort is stable */
return strcmp(a_filter->name, b_filter->name);
}
}
int ofono_voicecall_filter_register(const struct ofono_voicecall_filter *f)
{
if (!f || !f->name) {
return -EINVAL;
}
DBG("%s", f->name);
voicecall_filters = g_slist_insert_sorted(voicecall_filters, (void*)f,
voicecall_filter_sort);
return 0;
}
void ofono_voicecall_filter_unregister(const struct ofono_voicecall_filter *f)
{
if (f) {
DBG("%s", f->name);
voicecall_filters = g_slist_remove(voicecall_filters, f);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -78,8 +78,6 @@ struct ofono_voicecall {
struct ofono_emulator *pending_em; struct ofono_emulator *pending_em;
unsigned int pending_id; unsigned int pending_id;
struct voicecall_agent *vc_agent; struct voicecall_agent *vc_agent;
struct voicecall_filter_chain *filters;
GSList *incoming_filter_list;
}; };
struct voicecall { struct voicecall {
@@ -120,14 +118,6 @@ struct emulator_status {
int status; int status;
}; };
struct dial_filter_req {
struct ofono_voicecall *vc;
struct ofono_phone_number pn;
enum ofono_clir_option clir;
ofono_voicecall_cb_t cb;
void *data;
};
static const char *default_en_list[] = { "911", "112", NULL }; static const char *default_en_list[] = { "911", "112", NULL };
static const char *default_en_list_no_sim[] = { "119", "118", "999", "110", static const char *default_en_list_no_sim[] = { "119", "118", "999", "110",
"08", "000", NULL }; "08", "000", NULL };
@@ -704,9 +694,6 @@ static void voicecall_destroy(gpointer userdata)
{ {
struct voicecall *voicecall = (struct voicecall *)userdata; struct voicecall *voicecall = (struct voicecall *)userdata;
__ofono_voicecall_filter_chain_cancel(voicecall->vc->filters,
voicecall->call);
g_free(voicecall->call); g_free(voicecall->call);
g_free(voicecall->message); g_free(voicecall->message);
@@ -1509,7 +1496,7 @@ static void manager_dial_callback(const struct ofono_error *error, void *data)
} }
reply = __ofono_error_from_error(error, vc->pending); reply = __ofono_error_failed(vc->pending);
} }
__ofono_dbus_pending_reply(&vc->pending, reply); __ofono_dbus_pending_reply(&vc->pending, reply);
@@ -1518,168 +1505,6 @@ static void manager_dial_callback(const struct ofono_error *error, void *data)
voicecalls_emit_call_added(vc, v); voicecalls_emit_call_added(vc, v);
} }
static void dummy_callback(const struct ofono_error *error, void *data)
{
if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
DBG("command failed with error: %s",
telephony_error_to_str(error));
}
static void filter_hangup(struct voicecall *v)
{
struct ofono_voicecall *vc = v->vc;
const struct ofono_call *call = v->call;
const struct ofono_voicecall_driver *driver = vc->driver;
switch (call->status) {
case OFONO_CALL_STATUS_WAITING:
if (driver->set_udub) {
driver->set_udub(vc, dummy_callback, vc);
return;
} else if (driver->release_specific) {
driver->release_specific(vc, call->id,
dummy_callback, vc);
return;
}
break;
case OFONO_CALL_STATUS_ACTIVE:
case OFONO_CALL_STATUS_DIALING:
case OFONO_CALL_STATUS_ALERTING:
if (driver->hangup_active) {
driver->hangup_active(vc, dummy_callback, vc);
return;
}
/* no break */
default:
if (driver->release_specific) {
driver->release_specific(vc, call->id,
dummy_callback, vc);
return;
}
break;
}
ofono_warn("Couldn't disconnect %s call %d",
call_status_to_string(call->status), call->id);
}
static void filter_dial_check_cb(enum ofono_voicecall_filter_dial_result result,
void *data)
{
struct voicecall *v = data;
if (result == OFONO_VOICECALL_FILTER_DIAL_CONTINUE) {
DBG("No need to release %s call %d",
call_status_to_string(v->call->status), v->call->id);
} else {
DBG("Need to release %s call %d",
call_status_to_string(v->call->status), v->call->id);
filter_hangup(v);
}
}
static void filter_incoming_check_cb
(enum ofono_voicecall_filter_incoming_result result, void *data)
{
struct voicecall *v = data;
if (result == OFONO_VOICECALL_FILTER_INCOMING_CONTINUE) {
DBG("No need to release %s call %d",
call_status_to_string(v->call->status), v->call->id);
} else {
DBG("Need to release %s call %d",
call_status_to_string(v->call->status), v->call->id);
filter_hangup(v);
}
}
static void filter_incoming_cb(enum ofono_voicecall_filter_incoming_result res,
void *data)
{
struct voicecall *v = data;
struct ofono_voicecall *vc = v->vc;
vc->incoming_filter_list = g_slist_remove(vc->incoming_filter_list, v);
if (res == OFONO_VOICECALL_FILTER_INCOMING_HANGUP) {
if (vc->driver->release_specific) {
vc->driver->release_specific(vc, v->call->id,
dummy_callback, vc);
}
voicecall_destroy(v);
} else if (res == OFONO_VOICECALL_FILTER_INCOMING_IGNORE) {
voicecall_destroy(v);
} else if (voicecall_dbus_register(v)) {
struct ofono_voicecall *vc = v->vc;
vc->call_list = g_slist_insert_sorted(vc->call_list, v,
call_compare);
voicecalls_emit_call_added(vc, v);
}
}
void ofono_voicecall_filter_notify(struct ofono_voicecall *vc)
{
GSList *l;
struct voicecall *v;
/* Cancel all active filtering requests */
__ofono_voicecall_filter_chain_cancel(vc->filters, NULL);
/* Re-check incoming_filter_list */
for (l = vc->incoming_filter_list; l; l = l->next) {
v = l->data;
__ofono_voicecall_filter_chain_incoming(vc->filters, v->call,
filter_incoming_cb, NULL, v);
}
/* Re-check the calls that have already passed the filter */
for (l = vc->call_list; l; l = l->next) {
v = l->data;
if (v->call->direction == CALL_DIRECTION_MOBILE_ORIGINATED) {
__ofono_voicecall_filter_chain_dial_check(vc->filters,
v->call, filter_dial_check_cb, NULL, v);
} else {
__ofono_voicecall_filter_chain_incoming(vc->filters,
v->call, filter_incoming_check_cb, NULL, v);
}
}
}
static void dial_filter_cb(enum ofono_voicecall_filter_dial_result result,
void *req_data)
{
struct dial_filter_req *req = req_data;
if (result == OFONO_VOICECALL_FILTER_DIAL_BLOCK) {
struct ofono_error error;
error.type = OFONO_ERROR_TYPE_ERRNO;
error.error = EACCES;
req->cb(&error, req->data);
} else {
struct ofono_voicecall *vc = req->vc;
/* OFONO_VOICECALL_FILTER_DIAL_CONTINUE */
vc->driver->dial(vc, &req->pn, req->clir, req->cb, req->data);
}
}
static void dial_filter(struct ofono_voicecall *vc,
const struct ofono_phone_number *pn,
enum ofono_clir_option clir,
ofono_voicecall_cb_t cb, void *data)
{
struct dial_filter_req *req = g_new0(struct dial_filter_req, 1);
req->vc = vc;
req->pn = *pn;
req->clir = clir;
req->cb = cb;
req->data = data;
__ofono_voicecall_filter_chain_dial(vc->filters, &req->pn, clir,
dial_filter_cb, g_free, req);
}
static int voicecall_dial(struct ofono_voicecall *vc, const char *number, static int voicecall_dial(struct ofono_voicecall *vc, const char *number,
enum ofono_clir_option clir, enum ofono_clir_option clir,
ofono_voicecall_cb_t cb, void *data) ofono_voicecall_cb_t cb, void *data)
@@ -1717,11 +1542,7 @@ static int voicecall_dial(struct ofono_voicecall *vc, const char *number,
string_to_phone_number(number, &ph); string_to_phone_number(number, &ph);
/* No filtering for emergency calls */ vc->driver->dial(vc, &ph, clir, cb, vc);
if (is_emergency_number(vc, number))
vc->driver->dial(vc, &ph, clir, cb, vc);
else
dial_filter(vc, &ph, clir, cb, vc);
return 0; return 0;
} }
@@ -2451,18 +2272,6 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
__ofono_modem_callid_release(modem, id); __ofono_modem_callid_release(modem, id);
l = g_slist_find_custom(vc->incoming_filter_list, GUINT_TO_POINTER(id),
call_compare_by_id);
if (l) {
/* Incoming call was disconnected in the process of being
* filtered. voicecall_destroy cancels it. */
vc->incoming_filter_list = g_slist_delete_link
(vc->incoming_filter_list, l);
voicecall_destroy(l->data);
return;
}
l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(id), l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(id),
call_compare_by_id); call_compare_by_id);
@@ -2547,26 +2356,6 @@ void ofono_voicecall_notify(struct ofono_voicecall *vc,
call->status, call->id, call->phone_number.number, call->status, call->id, call->phone_number.number,
call->called_number.number, call->name); call->called_number.number, call->name);
l = g_slist_find_custom(vc->incoming_filter_list,
GUINT_TO_POINTER(call->id), call_compare_by_id);
if (l) {
/* The call has changed in the process of being filtered. */
DBG("Found filtered call with id: %d", call->id);
v = l->data;
/* Update the call */
voicecall_set_call_status(v, call->status);
voicecall_set_call_lineid(v, &call->phone_number,
call->clip_validity);
voicecall_set_call_calledid(v, &call->called_number);
voicecall_set_call_name(v, call->name, call->cnap_validity);
/* And restart the filtering */
__ofono_voicecall_filter_chain_restart(vc->filters, v->call);
return;
}
l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(call->id), l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(call->id),
call_compare_by_id); call_compare_by_id);
@@ -2632,16 +2421,6 @@ void ofono_voicecall_notify(struct ofono_voicecall *vc,
v->detect_time = time(NULL); v->detect_time = time(NULL);
if (call->status == CALL_STATUS_INCOMING ||
call->status == CALL_STATUS_WAITING) {
/* Incoming calls have to go through filtering */
vc->incoming_filter_list = g_slist_append
(vc->incoming_filter_list, v);
__ofono_voicecall_filter_chain_incoming(vc->filters, v->call,
filter_incoming_cb, NULL, v);
return;
}
if (!voicecall_dbus_register(v)) { if (!voicecall_dbus_register(v)) {
ofono_error("Unable to register voice call"); ofono_error("Unable to register voice call");
goto error; goto error;
@@ -3107,10 +2886,6 @@ static void voicecall_unregister(struct ofono_atom *atom)
g_slist_free(vc->call_list); g_slist_free(vc->call_list);
vc->call_list = NULL; vc->call_list = NULL;
/* voicecall_destroy cancels the filtering */
g_slist_free_full(vc->incoming_filter_list, voicecall_destroy);
vc->incoming_filter_list = NULL;
ofono_modem_remove_interface(modem, OFONO_VOICECALL_MANAGER_INTERFACE); ofono_modem_remove_interface(modem, OFONO_VOICECALL_MANAGER_INTERFACE);
g_dbus_unregister_interface(conn, path, g_dbus_unregister_interface(conn, path,
OFONO_VOICECALL_MANAGER_INTERFACE); OFONO_VOICECALL_MANAGER_INTERFACE);
@@ -3125,8 +2900,6 @@ static void voicecall_remove(struct ofono_atom *atom)
if (vc == NULL) if (vc == NULL)
return; return;
__ofono_voicecall_filter_chain_free(vc->filters);
if (vc->driver && vc->driver->remove) if (vc->driver && vc->driver->remove)
vc->driver->remove(vc); vc->driver->remove(vc);
@@ -3181,7 +2954,6 @@ struct ofono_voicecall *ofono_voicecall_create(struct ofono_modem *modem,
break; break;
} }
vc->filters = __ofono_voicecall_filter_chain_new(vc);
return vc; return vc;
} }
@@ -3930,7 +3702,6 @@ void ofono_voicecall_register(struct ofono_voicecall *vc)
vc->hfp_watch = __ofono_modem_add_atom_watch(modem, vc->hfp_watch = __ofono_modem_add_atom_watch(modem,
OFONO_ATOM_TYPE_EMULATOR_HFP, OFONO_ATOM_TYPE_EMULATOR_HFP,
emulator_hfp_watch, vc, NULL); emulator_hfp_watch, vc, NULL);
} }
void ofono_voicecall_remove(struct ofono_voicecall *vc) void ofono_voicecall_remove(struct ofono_voicecall *vc)
@@ -3948,11 +3719,6 @@ void *ofono_voicecall_get_data(struct ofono_voicecall *vc)
return vc->driver_data; return vc->driver_data;
} }
struct ofono_modem *ofono_voicecall_get_modem(struct ofono_voicecall *vc)
{
return __ofono_atom_get_modem(vc->atom);
}
int ofono_voicecall_get_next_callid(struct ofono_voicecall *vc) int ofono_voicecall_get_next_callid(struct ofono_voicecall *vc)
{ {
struct ofono_modem *modem; struct ofono_modem *modem;
@@ -4050,14 +3816,10 @@ static void dial_request(struct ofono_voicecall *vc)
struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom); struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
__ofono_modem_inc_emergency_mode(modem); __ofono_modem_inc_emergency_mode(modem);
/* No filtering for emergency calls */
vc->driver->dial(vc, &vc->dial_req->ph,
OFONO_CLIR_OPTION_DEFAULT, dial_request_cb, vc);
} else {
dial_filter(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
dial_request_cb, vc);
} }
vc->driver->dial(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
dial_request_cb, vc);
} }
static void dial_req_disconnect_cb(const struct ofono_error *error, void *data) static void dial_req_disconnect_cb(const struct ofono_error *error, void *data)

View File

@@ -21,9 +21,7 @@ TESTS="\
test-provision \ test-provision \
test-ril_util \ test-ril_util \
test-ril_config \ test-ril_config \
test-ril-transport \
test-sms-filter \ test-sms-filter \
test-voicecall-filter \
test-sailfish_cell_info \ test-sailfish_cell_info \
test-sailfish_cell_info_dbus \ test-sailfish_cell_info_dbus \
test-sailfish_manager \ test-sailfish_manager \

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ofono.h"
#include <ofono/ril-transport.h>
#include <string.h>
#include <errno.h>
static void test_null(void)
{
struct ofono_ril_transport noname;
memset(&noname, 0, sizeof(noname));
g_assert(ofono_ril_transport_register(NULL) == -EINVAL);
g_assert(ofono_ril_transport_register(&noname) == -EINVAL);
ofono_ril_transport_unregister(NULL);
ofono_ril_transport_unregister(&noname);
g_assert(!ofono_ril_transport_connect(NULL, NULL));
}
static void test_register(void)
{
struct ofono_ril_transport foo;
struct ofono_ril_transport bar;
memset(&foo, 0, sizeof(foo));
memset(&bar, 0, sizeof(bar));
foo.name = "foo";
bar.name = "bar";
g_assert(ofono_ril_transport_register(&foo) == 0);
g_assert(ofono_ril_transport_register(&bar) == 0);
g_assert(ofono_ril_transport_register(&bar) == (-EALREADY));
g_assert(!ofono_ril_transport_connect(foo.name, NULL));
g_assert(!ofono_ril_transport_connect("test", NULL));
ofono_ril_transport_unregister(&foo);
ofono_ril_transport_unregister(&bar);
}
static struct grilio_transport *test_connect_cb(GHashTable *params)
{
static int dummy;
return (void*)&dummy;
}
static void test_connect(void)
{
static const struct ofono_ril_transport test = {
.name = "test",
.api_version = OFONO_RIL_TRANSPORT_API_VERSION,
.connect = test_connect_cb
};
g_assert(ofono_ril_transport_register(&test) == 0);
/* The returned pointer points to a static variable, no need to free */
g_assert(ofono_ril_transport_connect(test.name, NULL));
ofono_ril_transport_unregister(&test);
}
#define TEST_(name) "/ril-transport/" name
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
__ofono_log_init("test-ril_util",
g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("null"), test_null);
g_test_add_func(TEST_("register"), test_register);
g_test_add_func(TEST_("connect"), test_connect);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -81,6 +81,27 @@ void test_parse_mcc_mnc(void)
g_assert(!op.tech); g_assert(!op.tech);
} }
void test_parse_int(void)
{
int value;
g_assert(!ril_parse_int(NULL, 0, NULL));
g_assert(!ril_parse_int("", 0, NULL));
g_assert(!ril_parse_int("garbage", 0, NULL));
g_assert(!ril_parse_int("0 trailing garbage", 0, NULL));
g_assert(ril_parse_int("0", 0, NULL));
g_assert(ril_parse_int("0", 0, &value));
g_assert(value == 0);
g_assert(!ril_parse_int("0x10000000000000000", 0, &value));
g_assert(!ril_parse_int("-2147483649", 0, &value));
g_assert(!ril_parse_int("4294967295", 0, &value));
g_assert(ril_parse_int(" 0x7fffffff ", 0, &value));
g_assert(value == 0x7fffffff);
g_assert(ril_parse_int(" 7fffffff ", 16, &value));
g_assert(value == 0x7fffffff);
g_assert(!ril_parse_int("0xffffffff", 0, &value));
}
void test_strings(void) void test_strings(void)
{ {
g_assert(!g_strcmp0(ril_error_to_string(RIL_E_SUCCESS), "OK")); g_assert(!g_strcmp0(ril_error_to_string(RIL_E_SUCCESS), "OK"));
@@ -107,6 +128,7 @@ int main(int argc, char *argv[])
g_test_add_func(TEST_("parse_tech"), test_parse_tech); g_test_add_func(TEST_("parse_tech"), test_parse_tech);
g_test_add_func(TEST_("parse_mcc_mnc"), test_parse_mcc_mnc); g_test_add_func(TEST_("parse_mcc_mnc"), test_parse_mcc_mnc);
g_test_add_func(TEST_("parse_int"), test_parse_int);
g_test_add_func(TEST_("strings"), test_strings); g_test_add_func(TEST_("strings"), test_strings);
return g_test_run(); return g_test_run();

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,8 @@ Source: %{name}-%{version}.tar.bz2
Requires: dbus Requires: dbus
Requires: systemd Requires: systemd
Requires: ofono-configs Requires: ofono-configs
Requires: libgrilio >= 1.0.25 Requires: libgrilio >= 1.0.21
Requires: libglibutil >= 1.0.30 Requires: libglibutil >= 1.0.23
Requires: mobile-broadband-provider-info Requires: mobile-broadband-provider-info
Requires(preun): systemd Requires(preun): systemd
Requires(post): systemd Requires(post): systemd
@@ -21,8 +21,8 @@ BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libudev) >= 145 BuildRequires: pkgconfig(libudev) >= 145
BuildRequires: pkgconfig(libwspcodec) >= 2.0 BuildRequires: pkgconfig(libwspcodec) >= 2.0
BuildRequires: pkgconfig(libgrilio) >= 1.0.25 BuildRequires: pkgconfig(libgrilio) >= 1.0.21
BuildRequires: pkgconfig(libglibutil) >= 1.0.30 BuildRequires: pkgconfig(libglibutil) >= 1.0.23
BuildRequires: pkgconfig(libdbuslogserver-dbus) BuildRequires: pkgconfig(libdbuslogserver-dbus)
BuildRequires: pkgconfig(libmce-glib) >= 1.0.5 BuildRequires: pkgconfig(libmce-glib) >= 1.0.5
BuildRequires: pkgconfig(mobile-broadband-provider-info) BuildRequires: pkgconfig(mobile-broadband-provider-info)