mirror of
https://github.com/sailfishos/ofono
synced 2025-11-28 21:51:05 +08:00
Compare commits
28 Commits
mer/1.14+g
...
mer/1.14+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c53260938 | ||
|
|
e3e691fb48 | ||
|
|
8fa99a07e8 | ||
|
|
23f92a5b3e | ||
|
|
94494f3a63 | ||
|
|
098b3d4a64 | ||
|
|
cfeb58f2a8 | ||
|
|
5f821b4a9a | ||
|
|
533d248288 | ||
|
|
4f512b6e56 | ||
|
|
ce3a5e5a0b | ||
|
|
c97ef76c93 | ||
|
|
95659d7c49 | ||
|
|
eb986f49e4 | ||
|
|
4691d385c0 | ||
|
|
0ddebfea70 | ||
|
|
2d1f2b0650 | ||
|
|
0ca5c87999 | ||
|
|
e3dcd67a1b | ||
|
|
99b9099082 | ||
|
|
ec74da107d | ||
|
|
50f146939f | ||
|
|
e7a07b4694 | ||
|
|
461d18f4a3 | ||
|
|
16ea57247d | ||
|
|
88f42f44c1 | ||
|
|
2aed3c3f66 | ||
|
|
9c9028b164 |
@@ -514,7 +514,7 @@ if PROVISION
|
||||
builtin_sources += plugins/mbpi.h plugins/mbpi.c
|
||||
|
||||
builtin_modules += provision
|
||||
builtin_sources += plugins/provision.c
|
||||
builtin_sources += plugins/provision.h plugins/provision.c
|
||||
|
||||
builtin_modules += cdma_provision
|
||||
builtin_sources += plugins/cdma-provision.c
|
||||
@@ -587,7 +587,7 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
|
||||
src/cdma-provision.c src/handsfree.c \
|
||||
src/handsfree-audio.c src/bluetooth.h \
|
||||
src/hfp.h src/sim-mnclength.c src/oemraw.c \
|
||||
src/siri.c
|
||||
src/siri.c src/voicecallagent.c
|
||||
|
||||
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
@@ -726,7 +726,8 @@ test_scripts = test/backtrace \
|
||||
test/hangup-multiparty \
|
||||
test/hangup-call \
|
||||
test/display-icon \
|
||||
test/set-msisdn
|
||||
test/set-msisdn \
|
||||
test/test-voicecallagent
|
||||
|
||||
if TEST
|
||||
testdir = $(pkglibdir)/test
|
||||
@@ -747,7 +748,8 @@ unit_tests = unit/test-common unit/test-util unit/test-idmap \
|
||||
unit/test-grilrequest \
|
||||
unit/test-grilreply \
|
||||
unit/test-grilunsol \
|
||||
unit/test-sms unit/test-cdmasms
|
||||
unit/test-sms unit/test-cdmasms \
|
||||
unit/test-provision
|
||||
|
||||
noinst_PROGRAMS = $(unit_tests) \
|
||||
unit/test-sms-root unit/test-mux unit/test-caif
|
||||
@@ -814,6 +816,13 @@ unit_test_grilunsol_SOURCES = unit/test-grilunsol.c $(gril_sources) \
|
||||
unit_test_grilunsol_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_grilunsol_OBJECTS)
|
||||
|
||||
unit_test_provision_SOURCES = unit/test-provision.c \
|
||||
plugins/provision.h plugins/provision.c \
|
||||
plugins/mbpi.c src/gprs-provision.c \
|
||||
src/log.c
|
||||
unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_provision_OBJECTS)
|
||||
|
||||
TESTS = $(unit_tests)
|
||||
|
||||
if TOOLS
|
||||
|
||||
@@ -198,6 +198,25 @@ Methods dict GetProperties()
|
||||
[service].Error.InvalidFormat
|
||||
[service].Error.Failed
|
||||
|
||||
void RegisterVoicecallAgent(object path)
|
||||
|
||||
Registers an agent which will be called whenever a
|
||||
specific voice call related event requiring a client
|
||||
action occurs. Currently, the only such action is
|
||||
playing a ringback tone locally.
|
||||
|
||||
Possible Errors: [service].Error.InProgress
|
||||
[service].Error.InvalidArguments
|
||||
[service].Error.InvalidFormat
|
||||
[service].Error.Failed
|
||||
|
||||
void UnregisterVoicecallAgent(object path)
|
||||
|
||||
Unregisters an agent.
|
||||
|
||||
Possible Errors: [service].Error.InvalidArguments
|
||||
[service].Error.Failed
|
||||
|
||||
Signals CallAdded(object path, dict properties)
|
||||
|
||||
Signal that is sent when a new call is added. It
|
||||
@@ -257,3 +276,26 @@ Properties array{string} EmergencyNumbers [readonly]
|
||||
of numbers provided by the specification and any
|
||||
extra numbers provisioned by the carrier on the
|
||||
SIM.
|
||||
|
||||
VoiceCallAgent Hierarchy
|
||||
========================
|
||||
|
||||
Service unique name
|
||||
Interface org.ofono.VoiceCallAgent
|
||||
Object path freely definable
|
||||
|
||||
Methods void RingbackTone(boolean playTone)
|
||||
|
||||
Requests the client to generate an alerting tone locally
|
||||
(3GPP 24.008; 5.2.1.5). This can happen when an outgoing
|
||||
voice call is made and network is not providing the
|
||||
alerting tone. Value 0 stands for "stop playing ringback
|
||||
tone" and 1 for "start playing ringback tone".
|
||||
|
||||
void Release() [noreply]
|
||||
|
||||
Agent is being released, possibly because of oFono
|
||||
terminating, voicecall interface is being torn down or
|
||||
modem is switched off. No UnregisterVoicecallAgent
|
||||
call is needed.
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ static int ril_call_barring_probe(struct ofono_call_barring *cb,
|
||||
|
||||
bd->ril = g_ril_clone(ril);
|
||||
ofono_call_barring_set_data(cb, bd);
|
||||
g_timeout_add_seconds(2, ril_delayed_register, cb);
|
||||
bd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,9 +235,8 @@ static void ril_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
list[i].phone_number.number[
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
|
||||
|
||||
list[i].time = parcel_r_int32(&rilp);
|
||||
}
|
||||
|
||||
list[i].time = parcel_r_int32(&rilp);
|
||||
}
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, nmbr_of_resps, list, cbd->data);
|
||||
|
||||
@@ -237,7 +237,7 @@ static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
|
||||
ofono_gprs_detached_notify(gprs);
|
||||
gd->notified = FALSE;
|
||||
gd->ofono_attached = FALSE;
|
||||
} else if (gd->notified) {
|
||||
} else if (gd->notified && check_if_really_searching()) {
|
||||
DBG("hide the searching state");
|
||||
status = NETWORK_REGISTRATION_STATUS_REGISTERED;
|
||||
ofono_gprs_status_notify(gprs, status);
|
||||
|
||||
@@ -573,6 +573,15 @@ error:
|
||||
ofono_error("Unable to notify ofono about nitz");
|
||||
}
|
||||
|
||||
gboolean check_if_really_searching()
|
||||
{
|
||||
int status = NETWORK_REGISTRATION_STATUS_SEARCHING;
|
||||
status = ofono_netreg_get_status(current_netreg);
|
||||
if (status == NETWORK_REGISTRATION_STATUS_SEARCHING)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint check_if_really_roaming(gint status)
|
||||
{
|
||||
const char *net_mcc = ofono_netreg_get_mcc(current_netreg);
|
||||
|
||||
@@ -38,14 +38,18 @@
|
||||
struct oem_raw_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static gboolean ril_oemraw_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_oem_raw *raw = user_data;
|
||||
struct oem_raw_data *od = ofono_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
|
||||
od->timer_id = 0;
|
||||
|
||||
ofono_oem_raw_dbus_register(raw);
|
||||
return FALSE; /* This makes the timeout a single-shot */
|
||||
}
|
||||
@@ -64,7 +68,8 @@ static int ril_oemraw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
|
||||
od->vendor = vendor;
|
||||
ofono_oem_raw_set_data(raw, od);
|
||||
|
||||
g_timeout_add_seconds(1, ril_oemraw_delayed_register, raw);
|
||||
od->timer_id = g_timeout_add_seconds(1, ril_oemraw_delayed_register,
|
||||
raw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -79,6 +84,9 @@ static void ril_oemraw_remove(struct ofono_oem_raw *raw)
|
||||
|
||||
ofono_oem_raw_set_data(raw, NULL);
|
||||
|
||||
if (od->timer_id)
|
||||
g_source_remove(od->timer_id);
|
||||
|
||||
g_ril_unref(od->ril);
|
||||
g_free(od);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,8 @@ struct ofono_sim *get_sim();
|
||||
|
||||
gint check_if_really_roaming(gint status);
|
||||
|
||||
gboolean check_if_really_searching();
|
||||
|
||||
void ril_util_free_sim_apps(struct sim_app **apps, guint num_apps);
|
||||
|
||||
struct cb_data {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Canonical, Ltd. All rights reserved.
|
||||
* Copyright (C) 2014 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
|
||||
@@ -792,10 +793,8 @@ static void ril_pin_change_state_cb(struct ril_msg *message, gpointer user_data)
|
||||
retries[passwd_type] = retry_count;
|
||||
sd->retries[passwd_type] = retries[passwd_type];
|
||||
|
||||
/*
|
||||
* TODO: re-bfactor to not use macro for FAILURE; doesn't return error!
|
||||
*/
|
||||
|
||||
DBG("result=%d passwd_type=%d retry_count=%d",
|
||||
message->error, passwd_type, retry_count);
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
g_ril_print_response_no_args(sd->ril, message);
|
||||
@@ -844,11 +843,53 @@ static void ril_pin_send(struct ofono_sim *sim, const char *passwd,
|
||||
}
|
||||
}
|
||||
|
||||
static int ril_perso_change_state(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type passwd_type,
|
||||
int enable, const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
struct sim_data *sd = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int request = 0;
|
||||
int ret = 0;
|
||||
sd->passwd_type = passwd_type;
|
||||
cbd->user = sd;
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
switch (passwd_type) {
|
||||
case OFONO_SIM_PASSWORD_PHNET_PIN:
|
||||
if (enable) {
|
||||
DBG("Not supported, enable=%d", enable);
|
||||
goto end;
|
||||
}
|
||||
request = RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION;
|
||||
parcel_w_int32(&rilp, RIL_PERSOSUBSTATE_SIM_NETWORK);
|
||||
parcel_w_string(&rilp, (char *) passwd);
|
||||
break;
|
||||
default:
|
||||
DBG("Not supported, type=%d", passwd_type);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = g_ril_send(sd->ril, request,
|
||||
rilp.data, rilp.size, ril_pin_change_state_cb,
|
||||
cbd, g_free);
|
||||
|
||||
g_ril_print_request(sd->ril, ret, request);
|
||||
|
||||
end:
|
||||
parcel_free(&rilp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ril_pin_change_state(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type passwd_type,
|
||||
int enable, const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
DBG("passwd_type=%d", passwd_type);
|
||||
struct sim_data *sd = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
@@ -886,9 +927,9 @@ static void ril_pin_change_state(struct ofono_sim *sim,
|
||||
parcel_w_string(&rilp, "P2");
|
||||
break;
|
||||
case OFONO_SIM_PASSWORD_PHNET_PIN:
|
||||
g_ril_append_print_buf(sd->ril, "(PN,");
|
||||
parcel_w_string(&rilp, "PN");
|
||||
break;
|
||||
ret = ril_perso_change_state(sim, passwd_type, enable, passwd,
|
||||
cb, data);
|
||||
goto end;
|
||||
case OFONO_SIM_PASSWORD_PHNETSUB_PIN:
|
||||
g_ril_append_print_buf(sd->ril, "(PU,");
|
||||
parcel_w_string(&rilp, "PU");
|
||||
@@ -902,8 +943,7 @@ static void ril_pin_change_state(struct ofono_sim *sim,
|
||||
parcel_w_string(&rilp, "PC");
|
||||
break;
|
||||
default:
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
@@ -930,6 +970,7 @@ static void ril_pin_change_state(struct ofono_sim *sim,
|
||||
|
||||
g_ril_print_request(sd->ril, ret, request);
|
||||
|
||||
end:
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -1112,17 +1153,6 @@ static struct ofono_sim_driver driver = {
|
||||
.change_passwd = ril_change_passwd,
|
||||
.query_pin_retries = ril_query_pin_retries,
|
||||
/*
|
||||
* TODO: Implmenting PIN/PUK support requires defining
|
||||
* the following driver methods.
|
||||
*
|
||||
* In the meanwhile, as long as the SIM card is present,
|
||||
* and unlocked, the core SIM code will check for the
|
||||
* presence of query_passwd_state, and if null, then the
|
||||
* function sim_initialize_after_pin() is called.
|
||||
*
|
||||
* .query_pin_retries = ril_pin_retries_query,
|
||||
* .query_locked = ril_pin_query_enabled,
|
||||
*
|
||||
* TODO: Implementing SIM write file IO support requires
|
||||
* the following functions to be defined.
|
||||
*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
* Copyright (C) 2014 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -86,6 +86,21 @@ struct lastcause_req {
|
||||
static void send_one_dtmf(struct voicecall_data *vd);
|
||||
static void clear_dtmf_queue(struct voicecall_data *vd);
|
||||
|
||||
/*
|
||||
* structs ofono_voicecall and voicecall are fully defined
|
||||
* in src/voicecall.c; we need (read) access to the
|
||||
* call objects, so partially redefine them here.
|
||||
*/
|
||||
struct ofono_voicecall {
|
||||
GSList *call_list;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct voicecall {
|
||||
struct ofono_call *call;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
static void lastcause_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct lastcause_req *reqdata = user_data;
|
||||
@@ -99,11 +114,38 @@ static void lastcause_cb(struct ril_msg *message, gpointer user_data)
|
||||
if (parcel_r_int32(&rilp) > 0)
|
||||
last_cause = parcel_r_int32(&rilp);
|
||||
|
||||
/*
|
||||
* Not all call control cause values specified in 3GPP TS 24.008
|
||||
* "Mobile radio interface Layer 3 specification; Core network protocols",
|
||||
* Annex H, are properly reflected in the RIL API. For example, cause
|
||||
* #21 "call rejected" is mapped to CALL_FAIL_ERROR_UNSPECIFIED, and
|
||||
* thus indistinguishable from a network failure.
|
||||
* We signal disconnect reason "remote" for cause values
|
||||
* - #16 "normal call clearing"
|
||||
* - #17 "user busy"
|
||||
* - UNSPECIFIED for MO calls that are not yet connected
|
||||
* , and disconnect reason "network" otherwise.
|
||||
*/
|
||||
ofono_info("Call %d ended with RIL cause %d", id, last_cause);
|
||||
if (last_cause == CALL_FAIL_NORMAL || last_cause == CALL_FAIL_BUSY) {
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
}
|
||||
|
||||
if (last_cause == CALL_FAIL_ERROR_UNSPECIFIED) {
|
||||
GSList *l;
|
||||
struct voicecall *v;
|
||||
for (l = vc->call_list; l; l = l->next) {
|
||||
v = l->data;
|
||||
if (v->call->id == id) {
|
||||
if (v->call->status == CALL_STATUS_DIALING
|
||||
|| v->call->status == CALL_STATUS_ALERTING) {
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ofono_voicecall_disconnected(vc, id, reason, NULL);
|
||||
}
|
||||
|
||||
@@ -727,6 +769,23 @@ static gboolean enable_supp_svc(gpointer user_data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_ringback_tone_notify(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct parcel rilp;
|
||||
struct ofono_voicecall *vc = user_data;
|
||||
gboolean playTone = FALSE;
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
if (message->req == RIL_UNSOL_RINGBACK_TONE) {
|
||||
if (parcel_r_int32(&rilp) > 0)
|
||||
playTone = parcel_r_int32(&rilp);
|
||||
DBG("play ringback tone: %d", playTone);
|
||||
ofono_voicecall_ringback_tone_notify(vc, playTone);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_voicecall *vc = user_data;
|
||||
@@ -747,6 +806,10 @@ static gboolean ril_delayed_register(gpointer user_data)
|
||||
g_ril_register(vd->ril, RIL_UNSOL_SUPP_SVC_NOTIFICATION,
|
||||
ril_ss_notify, vc);
|
||||
|
||||
/* Register for ringback tone notifications */
|
||||
g_ril_register(vd->ril, RIL_UNSOL_RINGBACK_TONE,
|
||||
ril_ringback_tone_notify, vc);
|
||||
|
||||
/* request supplementary service notifications*/
|
||||
enable_supp_svc(vc);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[Unit]
|
||||
Description=DUN service
|
||||
After=syslog.target
|
||||
Requires=dbus.service
|
||||
After=dbus.service
|
||||
|
||||
[Service]
|
||||
Type=dbus
|
||||
|
||||
@@ -31,6 +31,7 @@ extern "C" {
|
||||
struct ofono_gprs_provision_data {
|
||||
enum ofono_gprs_context_type type;
|
||||
enum ofono_gprs_proto proto;
|
||||
char *provider_name;
|
||||
char *name;
|
||||
char *apn;
|
||||
char *username;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2014 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
|
||||
@@ -171,6 +172,9 @@ void ofono_voicecall_ssn_mt_notify(struct ofono_voicecall *vc, unsigned int id,
|
||||
int code, int index,
|
||||
const struct ofono_phone_number *ph);
|
||||
|
||||
void ofono_voicecall_ringback_tone_notify(struct ofono_voicecall *vc,
|
||||
const ofono_bool_t playTone);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -53,6 +53,7 @@ enum MBPI_ERROR {
|
||||
struct gsm_data {
|
||||
const char *match_mcc;
|
||||
const char *match_mnc;
|
||||
char *provider_name;
|
||||
GSList *apns;
|
||||
gboolean match_found;
|
||||
gboolean allow_duplicates;
|
||||
@@ -84,6 +85,7 @@ static GQuark mbpi_error_quark(void)
|
||||
|
||||
void mbpi_ap_free(struct ofono_gprs_provision_data *ap)
|
||||
{
|
||||
g_free(ap->provider_name);
|
||||
g_free(ap->name);
|
||||
g_free(ap->apn);
|
||||
g_free(ap->username);
|
||||
@@ -117,6 +119,7 @@ static void text_handler(GMarkupParseContext *context,
|
||||
{
|
||||
char **string = userdata;
|
||||
|
||||
g_free(*string);
|
||||
*string = g_strndup(text, text_len);
|
||||
}
|
||||
|
||||
@@ -288,6 +291,7 @@ static void apn_handler(GMarkupParseContext *context, struct gsm_data *gsm,
|
||||
}
|
||||
|
||||
ap = g_new0(struct ofono_gprs_provision_data, 1);
|
||||
ap->provider_name = g_strdup(gsm->provider_name);
|
||||
ap->apn = g_strdup(apn);
|
||||
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||
ap->proto = OFONO_GPRS_PROTO_IP;
|
||||
@@ -454,6 +458,44 @@ static const GMarkupParser provider_parser = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void gsm_provider_start(GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **atribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer userdata, GError **error)
|
||||
{
|
||||
struct gsm_data *gsm = userdata;
|
||||
|
||||
if (g_str_equal(element_name, "name")) {
|
||||
g_free(gsm->provider_name);
|
||||
gsm->provider_name = NULL;
|
||||
g_markup_parse_context_push(context, &text_parser,
|
||||
&gsm->provider_name);
|
||||
} else if (g_str_equal(element_name, "gsm")) {
|
||||
gsm->match_found = FALSE;
|
||||
g_markup_parse_context_push(context, &gsm_parser, gsm);
|
||||
} else if (g_str_equal(element_name, "cdma"))
|
||||
g_markup_parse_context_push(context, &skip_parser, NULL);
|
||||
}
|
||||
|
||||
static void gsm_provider_end(GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer userdata, GError **error)
|
||||
{
|
||||
if (g_str_equal(element_name, "name") ||
|
||||
g_str_equal(element_name, "gsm") ||
|
||||
g_str_equal(element_name, "cdma"))
|
||||
g_markup_parse_context_pop(context);
|
||||
}
|
||||
|
||||
static const GMarkupParser gsm_provider_parser = {
|
||||
gsm_provider_start,
|
||||
gsm_provider_end,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void toplevel_gsm_start(GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
const gchar **atribute_names,
|
||||
@@ -462,19 +504,15 @@ static void toplevel_gsm_start(GMarkupParseContext *context,
|
||||
{
|
||||
struct gsm_data *gsm = userdata;
|
||||
|
||||
if (g_str_equal(element_name, "gsm")) {
|
||||
gsm->match_found = FALSE;
|
||||
g_markup_parse_context_push(context, &gsm_parser, gsm);
|
||||
} else if (g_str_equal(element_name, "cdma"))
|
||||
g_markup_parse_context_push(context, &skip_parser, NULL);
|
||||
if (g_str_equal(element_name, "provider"))
|
||||
g_markup_parse_context_push(context, &gsm_provider_parser, gsm);
|
||||
}
|
||||
|
||||
static void toplevel_gsm_end(GMarkupParseContext *context,
|
||||
const gchar *element_name,
|
||||
gpointer userdata, GError **error)
|
||||
{
|
||||
if (g_str_equal(element_name, "gsm") ||
|
||||
g_str_equal(element_name, "cdma"))
|
||||
if (g_str_equal(element_name, "provider"))
|
||||
g_markup_parse_context_pop(context);
|
||||
}
|
||||
|
||||
@@ -591,6 +629,7 @@ GSList *mbpi_lookup_apn(const char *mcc, const char *mnc,
|
||||
gsm.apns = NULL;
|
||||
}
|
||||
|
||||
g_free(gsm.provider_name);
|
||||
return gsm.apns;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -36,57 +37,102 @@
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/gprs-provision.h>
|
||||
|
||||
#include "provision.h"
|
||||
#include "mbpi.h"
|
||||
|
||||
/* Returns the list containing exactly one INTERNET and one MMS access point */
|
||||
static GSList *provision_normalize_apn_list(GSList *apns)
|
||||
static GSList *provision_normalize_apn_list(GSList *apns, const char* spn)
|
||||
{
|
||||
struct ofono_gprs_provision_data *internet = NULL;
|
||||
struct ofono_gprs_provision_data *mms = NULL;
|
||||
GSList *l = apns;
|
||||
struct ofono_gprs_provision_data *best_internet = NULL;
|
||||
struct ofono_gprs_provision_data *best_mms = NULL;
|
||||
struct ofono_gprs_provision_data *second_best_internet = NULL;
|
||||
struct ofono_gprs_provision_data *second_best_mms = NULL;
|
||||
GSList *best_apns = NULL;
|
||||
GSList *l;
|
||||
|
||||
/* 1. save the first found internet APN and the first MMS APN */
|
||||
l = apns;
|
||||
while (l != NULL) {
|
||||
GSList *next = l->next;
|
||||
struct ofono_gprs_provision_data *ap = l->data;
|
||||
|
||||
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET && !internet) {
|
||||
internet = ap;
|
||||
} else if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS && !mms) {
|
||||
mms = ap;
|
||||
} else {
|
||||
/* Remove duplicate and unnecessary access points */
|
||||
DBG("Discarding APN: '%s' Name: '%s' Type: %s",
|
||||
ap->apn, ap->name, mbpi_ap_type(ap->type));
|
||||
mbpi_ap_free(ap);
|
||||
apns = g_slist_remove_link(apns, l);
|
||||
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET
|
||||
&& !best_internet) {
|
||||
best_internet = ap;
|
||||
} else if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS
|
||||
&& !best_mms) {
|
||||
best_mms = ap;
|
||||
}
|
||||
l = next;
|
||||
}
|
||||
|
||||
if (!internet) {
|
||||
internet = g_try_new0(struct ofono_gprs_provision_data, 1);
|
||||
if (internet) {
|
||||
internet->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||
internet->name = g_strdup("Internet");
|
||||
internet->apn = g_strdup("internet");
|
||||
apns = g_slist_append(apns, internet);
|
||||
/*
|
||||
* 2. if there is an SPN given, save the first internet APN and the
|
||||
* first MMS APN matching the SPN (partially, case-insensitively)
|
||||
* */
|
||||
if (spn) {
|
||||
second_best_internet = best_internet;
|
||||
best_internet = NULL;
|
||||
second_best_mms = best_mms;
|
||||
best_mms = NULL;
|
||||
|
||||
l = apns;
|
||||
while (l != NULL) {
|
||||
GSList *next = l->next;
|
||||
struct ofono_gprs_provision_data *ap = l->data;
|
||||
|
||||
if ((ap->provider_name && strcasestr(ap->provider_name, spn))
|
||||
|| (ap->name && strcasestr(ap->name, spn))
|
||||
|| (ap->apn && strcasestr(ap->apn, spn))) {
|
||||
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET
|
||||
&& !best_internet) {
|
||||
best_internet = ap;
|
||||
} else if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS
|
||||
&& !best_mms) {
|
||||
best_mms = ap;
|
||||
}
|
||||
}
|
||||
l = next;
|
||||
}
|
||||
|
||||
/* no better match found */
|
||||
if (!best_internet)
|
||||
best_internet = second_best_internet;
|
||||
if (!best_mms)
|
||||
best_mms = second_best_mms;
|
||||
}
|
||||
|
||||
/* 3. if none found yet, create APNs with default values */
|
||||
if (!best_internet) {
|
||||
best_internet = g_try_new0(struct ofono_gprs_provision_data, 1);
|
||||
if (best_internet) {
|
||||
best_internet->type =
|
||||
OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||
best_internet->name =
|
||||
g_strdup("Internet");
|
||||
best_internet->apn =
|
||||
g_strdup("internet");
|
||||
}
|
||||
}
|
||||
|
||||
if (!mms) {
|
||||
mms = g_try_new0(struct ofono_gprs_provision_data, 1);
|
||||
if (mms) {
|
||||
mms->type = OFONO_GPRS_CONTEXT_TYPE_MMS;
|
||||
mms->name = g_strdup("MMS");
|
||||
mms->apn = g_strdup("mms");
|
||||
apns = g_slist_append(apns, mms);
|
||||
if (!best_mms) {
|
||||
best_mms = g_try_new0(struct ofono_gprs_provision_data, 1);
|
||||
if (best_mms) {
|
||||
best_mms->type =
|
||||
OFONO_GPRS_CONTEXT_TYPE_MMS;
|
||||
best_mms->name =
|
||||
g_strdup("MMS");
|
||||
best_mms->apn =
|
||||
g_strdup("mms");
|
||||
}
|
||||
}
|
||||
|
||||
return apns;
|
||||
best_apns = g_slist_append(best_apns, best_internet);
|
||||
best_apns = g_slist_append(best_apns, best_mms);
|
||||
return best_apns;
|
||||
}
|
||||
|
||||
static int provision_get_settings(const char *mcc, const char *mnc,
|
||||
int provision_get_settings(const char *mcc, const char *mnc,
|
||||
const char *spn,
|
||||
struct ofono_gprs_provision_data **settings,
|
||||
int *count)
|
||||
@@ -97,7 +143,7 @@ static int provision_get_settings(const char *mcc, const char *mnc,
|
||||
int ap_count;
|
||||
int i;
|
||||
|
||||
DBG("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn);
|
||||
ofono_info("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn);
|
||||
|
||||
/*
|
||||
* Passing FALSE to mbpi_lookup_apn() would return
|
||||
@@ -109,13 +155,14 @@ static int provision_get_settings(const char *mcc, const char *mnc,
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
apns = provision_normalize_apn_list(apns);
|
||||
ofono_info("Found %d APs in MBPI", g_slist_length(apns));
|
||||
apns = provision_normalize_apn_list(apns, spn);
|
||||
if (apns == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
ap_count = g_slist_length(apns);
|
||||
|
||||
DBG("Found %d APs", ap_count);
|
||||
ofono_info("Provisioning %d APs", ap_count);
|
||||
|
||||
*settings = g_try_new0(struct ofono_gprs_provision_data, ap_count);
|
||||
if (*settings == NULL) {
|
||||
@@ -134,11 +181,11 @@ static int provision_get_settings(const char *mcc, const char *mnc,
|
||||
for (l = apns, i = 0; l; l = l->next, i++) {
|
||||
struct ofono_gprs_provision_data *ap = l->data;
|
||||
|
||||
DBG("Name: '%s'", ap->name);
|
||||
DBG("APN: '%s'", ap->apn);
|
||||
DBG("Type: %s", mbpi_ap_type(ap->type));
|
||||
DBG("Username: '%s'", ap->username);
|
||||
DBG("Password: '%s'", ap->password);
|
||||
ofono_info("Name: '%s'", ap->name);
|
||||
ofono_info("APN: '%s'", ap->apn);
|
||||
ofono_info("Type: %s", mbpi_ap_type(ap->type));
|
||||
ofono_info("Username: '%s'", ap->username);
|
||||
ofono_info("Password: '%s'", ap->password);
|
||||
|
||||
memcpy(*settings + i, ap,
|
||||
sizeof(struct ofono_gprs_provision_data));
|
||||
|
||||
28
ofono/plugins/provision.h
Normal file
28
ofono/plugins/provision.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2014 Jolla. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
struct ofono_gprs_provision_data;
|
||||
|
||||
int provision_get_settings(const char *mcc, const char *mnc,
|
||||
const char *spn,
|
||||
struct ofono_gprs_provision_data **settings,
|
||||
int *count);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<allow send_interface="org.ofono.SmartMessagingAgent"/>
|
||||
<allow send_interface="org.ofono.PositioningRequestAgent"/>
|
||||
<allow send_interface="org.ofono.HandsfreeAudioAgent"/>
|
||||
<allow send_interface="org.ofono.VoiceCallAgent"/>
|
||||
</policy>
|
||||
|
||||
<policy user="radio">
|
||||
@@ -25,6 +26,7 @@
|
||||
<allow send_interface="org.ofono.SmartMessagingAgent"/>
|
||||
<allow send_interface="org.ofono.PositioningRequestAgent"/>
|
||||
<allow send_interface="org.ofono.HandsfreeAudioAgent"/>
|
||||
<allow send_interface="org.ofono.VoiceCallAgent"/>
|
||||
</policy>
|
||||
|
||||
<policy at_console="true">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2014 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
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "simutil.h"
|
||||
#include "smsutil.h"
|
||||
#include "storage.h"
|
||||
#include "voicecallagent.h"
|
||||
|
||||
#define MAX_VOICE_CALLS 16
|
||||
|
||||
@@ -75,6 +77,7 @@ struct ofono_voicecall {
|
||||
ofono_voicecall_cb_t release_queue_done_cb;
|
||||
struct ofono_emulator *pending_em;
|
||||
unsigned int pending_id;
|
||||
struct voicecall_agent *vc_agent;
|
||||
};
|
||||
|
||||
struct voicecall {
|
||||
@@ -2140,6 +2143,72 @@ static DBusMessage *manager_get_calls(DBusConnection *conn,
|
||||
return reply;
|
||||
}
|
||||
|
||||
static void voicecall_agent_notify(gpointer user_data)
|
||||
{
|
||||
struct ofono_voicecall *vc = user_data;
|
||||
vc->vc_agent = NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *voicecall_register_agent(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ofono_voicecall *vc = data;
|
||||
const char *agent_path;
|
||||
|
||||
if (vc->vc_agent)
|
||||
return __ofono_error_busy(msg);
|
||||
|
||||
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
|
||||
&agent_path, DBUS_TYPE_INVALID) == FALSE)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
if (!__ofono_dbus_valid_object_path(agent_path))
|
||||
return __ofono_error_invalid_format(msg);
|
||||
|
||||
vc->vc_agent = voicecall_agent_new(agent_path,
|
||||
dbus_message_get_sender(msg));
|
||||
|
||||
if (vc->vc_agent == NULL)
|
||||
return __ofono_error_failed(msg);
|
||||
|
||||
voicecall_agent_set_removed_notify(vc->vc_agent,
|
||||
voicecall_agent_notify, vc);
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
}
|
||||
|
||||
static DBusMessage *voicecall_unregister_agent(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ofono_voicecall *vc = data;
|
||||
const char *agent_path;
|
||||
const char *agent_bus = dbus_message_get_sender(msg);
|
||||
|
||||
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &agent_path,
|
||||
DBUS_TYPE_INVALID) == FALSE)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
if (vc->vc_agent == NULL)
|
||||
return __ofono_error_failed(msg);
|
||||
|
||||
if (!voicecall_agent_matches(vc->vc_agent, agent_path, agent_bus))
|
||||
return __ofono_error_access_denied(msg);
|
||||
|
||||
if (vc->vc_agent) {
|
||||
voicecall_agent_free(vc->vc_agent);
|
||||
vc->vc_agent = NULL;
|
||||
}
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
}
|
||||
|
||||
void ofono_voicecall_ringback_tone_notify(struct ofono_voicecall *vc,
|
||||
const ofono_bool_t playTone)
|
||||
{
|
||||
if (vc->vc_agent)
|
||||
voicecall_agent_ringback_tone(vc->vc_agent, playTone);
|
||||
}
|
||||
|
||||
static const GDBusMethodTable manager_methods[] = {
|
||||
{ GDBUS_METHOD("GetProperties",
|
||||
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
|
||||
@@ -2172,6 +2241,12 @@ static const GDBusMethodTable manager_methods[] = {
|
||||
{ GDBUS_METHOD("GetCalls",
|
||||
NULL, GDBUS_ARGS({ "calls_with_properties", "a(oa{sv})" }),
|
||||
manager_get_calls) },
|
||||
{ GDBUS_ASYNC_METHOD("RegisterVoicecallAgent",
|
||||
GDBUS_ARGS({ "path", "o" }), NULL,
|
||||
voicecall_register_agent) },
|
||||
{ GDBUS_ASYNC_METHOD("UnregisterVoicecallAgent",
|
||||
GDBUS_ARGS({ "path", "o" }), NULL,
|
||||
voicecall_unregister_agent) },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -2744,6 +2819,11 @@ static void voicecall_unregister(struct ofono_atom *atom)
|
||||
|
||||
voicecall_close_settings(vc);
|
||||
|
||||
if (vc->vc_agent) {
|
||||
voicecall_agent_free(vc->vc_agent);
|
||||
vc->vc_agent = 0;
|
||||
}
|
||||
|
||||
if (vc->sim_state_watch) {
|
||||
ofono_sim_remove_state_watch(vc->sim, vc->sim_state_watch);
|
||||
vc->sim_state_watch = 0;
|
||||
|
||||
131
ofono/src/voicecallagent.c
Normal file
131
ofono/src/voicecallagent.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2014 Jolla Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <gdbus.h>
|
||||
|
||||
#include "ofono.h"
|
||||
#include "voicecallagent.h"
|
||||
|
||||
#define OFONO_VOICECALL_AGENT_INTERFACE "org.ofono.VoiceCallAgent"
|
||||
|
||||
struct voicecall_agent {
|
||||
char *path; /* Agent Path */
|
||||
char *bus; /* Agent bus */
|
||||
guint disconnect_watch; /* DBus disconnect watch */
|
||||
ofono_destroy_func removed_cb;
|
||||
void *removed_data;
|
||||
};
|
||||
|
||||
void voicecall_agent_ringback_tone(struct voicecall_agent *agent,
|
||||
const ofono_bool_t playTone)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
DBusMessage *message = dbus_message_new_method_call(
|
||||
agent->bus, agent->path,
|
||||
OFONO_VOICECALL_AGENT_INTERFACE,
|
||||
"RingbackTone");
|
||||
|
||||
if (message == NULL)
|
||||
return;
|
||||
|
||||
if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &playTone,
|
||||
DBUS_TYPE_INVALID))
|
||||
return;
|
||||
|
||||
dbus_message_set_no_reply(message, TRUE);
|
||||
g_dbus_send_message(conn, message);
|
||||
}
|
||||
|
||||
void voicecall_agent_send_release(struct voicecall_agent *agent)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
DBusMessage *message = dbus_message_new_method_call(
|
||||
agent->bus, agent->path,
|
||||
OFONO_VOICECALL_AGENT_INTERFACE,
|
||||
"Release");
|
||||
|
||||
if (message == NULL)
|
||||
return;
|
||||
|
||||
dbus_message_set_no_reply(message, TRUE);
|
||||
g_dbus_send_message(conn, message);
|
||||
}
|
||||
|
||||
void voicecall_agent_set_removed_notify(struct voicecall_agent *agent,
|
||||
ofono_destroy_func destroy,
|
||||
void *user_data)
|
||||
{
|
||||
agent->removed_cb = destroy;
|
||||
agent->removed_data = user_data; /* voicecall atom (not owned) */
|
||||
}
|
||||
|
||||
void voicecall_agent_free(struct voicecall_agent *agent)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
|
||||
if (agent->disconnect_watch) {
|
||||
voicecall_agent_send_release(agent);
|
||||
g_dbus_remove_watch(conn, agent->disconnect_watch);
|
||||
agent->disconnect_watch = 0;
|
||||
}
|
||||
|
||||
if (agent->removed_cb)
|
||||
agent->removed_cb(agent->removed_data);
|
||||
|
||||
g_free(agent->path);
|
||||
g_free(agent->bus);
|
||||
g_free(agent);
|
||||
}
|
||||
|
||||
ofono_bool_t voicecall_agent_matches(struct voicecall_agent *agent,
|
||||
const char *path, const char *sender)
|
||||
{
|
||||
return g_str_equal(agent->path, path) &&
|
||||
g_str_equal(agent->bus, sender);
|
||||
}
|
||||
|
||||
void voicecall_agent_disconnect_cb(DBusConnection *conn, void *user_data)
|
||||
{
|
||||
struct voicecall_agent *agent = user_data;
|
||||
|
||||
agent->disconnect_watch = 0;
|
||||
voicecall_agent_free(agent);
|
||||
}
|
||||
|
||||
struct voicecall_agent *voicecall_agent_new(const char *path,
|
||||
const char *sender)
|
||||
{
|
||||
struct voicecall_agent *agent = g_try_new0(struct voicecall_agent, 1);
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
|
||||
if (agent == NULL)
|
||||
return NULL;
|
||||
|
||||
agent->path = g_strdup(path);
|
||||
agent->bus = g_strdup(sender);
|
||||
|
||||
agent->disconnect_watch = g_dbus_add_disconnect_watch(conn, sender,
|
||||
voicecall_agent_disconnect_cb,
|
||||
agent, NULL);
|
||||
|
||||
return agent;
|
||||
}
|
||||
40
ofono/src/voicecallagent.h
Normal file
40
ofono/src/voicecallagent.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2014 Jolla Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
struct voicecall_agent;
|
||||
|
||||
void voicecall_agent_ringback_tone(struct voicecall_agent *agent,
|
||||
const ofono_bool_t playTone);
|
||||
|
||||
void voicecall_agent_set_removed_notify(struct voicecall_agent *agent,
|
||||
ofono_destroy_func removed_cb,
|
||||
void *user_data);
|
||||
|
||||
void voicecall_agent_free(struct voicecall_agent *agent);
|
||||
|
||||
ofono_bool_t voicecall_agent_matches(struct voicecall_agent *agent,
|
||||
const char *path, const char *sender);
|
||||
|
||||
struct voicecall_agent *voicecall_agent_new(const char *path,
|
||||
const char *sender);
|
||||
|
||||
void voicecall_agent_disconnect_cb(DBusConnection *conn,
|
||||
void *user_data);
|
||||
48
ofono/test/test-voicecallagent
Executable file
48
ofono/test/test-voicecallagent
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import gobject
|
||||
|
||||
import sys
|
||||
import dbus
|
||||
import dbus.service
|
||||
import dbus.mainloop.glib
|
||||
|
||||
class VoiceCallAgent(dbus.service.Object):
|
||||
@dbus.service.method("org.ofono.VoiceCallAgent",
|
||||
in_signature="", out_signature="")
|
||||
def Release(self):
|
||||
print "Agent got Release"
|
||||
mainloop.quit()
|
||||
|
||||
@dbus.service.method("org.ofono.VoiceCallAgent",
|
||||
in_signature="b", out_signature="")
|
||||
def RingbackTone(self, playTone):
|
||||
print "Agent got playTone notification: %d" % playTone
|
||||
|
||||
if __name__ == '__main__':
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
manager = dbus.Interface(bus.get_object("org.ofono", "/"),
|
||||
"org.ofono.Manager")
|
||||
|
||||
modems = manager.GetModems()
|
||||
|
||||
for path, properties in modems:
|
||||
if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
|
||||
continue
|
||||
|
||||
vcm = dbus.Interface(bus.get_object('org.ofono', path),
|
||||
'org.ofono.VoiceCallManager')
|
||||
|
||||
path = "/test/agent"
|
||||
agent = VoiceCallAgent(bus, path)
|
||||
vcm.RegisterVoicecallAgent(agent)
|
||||
print "Agent registered"
|
||||
mainloop = gobject.MainLoop()
|
||||
|
||||
try:
|
||||
mainloop.run()
|
||||
except KeyboardInterrupt:
|
||||
vcm.UnregisterVoicecallAgent(path)
|
||||
print "Agent unregistered (interrupt)"
|
||||
99
ofono/unit/test-provision.c
Normal file
99
ofono/unit/test-provision.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2014 Jolla. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
struct ofono_modem;
|
||||
#include <gprs-provision.h>
|
||||
#include "plugins/mbpi.h"
|
||||
#include "plugins/provision.h"
|
||||
|
||||
|
||||
void get_and_print_settings(const char *mcc, const char *mnc,
|
||||
const char *spn)
|
||||
{
|
||||
struct ofono_gprs_provision_data *settings;
|
||||
int count;
|
||||
int i;
|
||||
provision_get_settings(mcc, mnc, spn, &settings, &count);
|
||||
g_print("Found %d contexts for (%s/%s/%s):\n", count, mcc, mnc, spn);
|
||||
for (i = 0; i < count; i++){
|
||||
struct ofono_gprs_provision_data ap = settings[i];
|
||||
g_print(" Name: %s\n", ap.name);
|
||||
g_print(" APN: %s\n", ap.apn);
|
||||
g_print(" Type: %s\n", mbpi_ap_type(ap.type));
|
||||
if (ap.username)
|
||||
g_print(" Username: %s\n", ap.username);
|
||||
if (ap.password)
|
||||
g_print(" Password: %s\n", ap.password);
|
||||
if (ap.message_proxy)
|
||||
g_print(" MMS proxy: %s\n", ap.message_proxy);
|
||||
if (ap.message_center)
|
||||
g_print(" MMS center: %s\n", ap.message_center);
|
||||
g_print("----------\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_settings(void)
|
||||
{
|
||||
/* not in database */
|
||||
get_and_print_settings("999", "999", NULL);
|
||||
|
||||
/* partial and case-insensitive matching */
|
||||
get_and_print_settings("244", "91", "sonera");
|
||||
get_and_print_settings("244", "91", "sONErA");
|
||||
get_and_print_settings("244", "91", "sone");
|
||||
get_and_print_settings("244", "91", "nera");
|
||||
|
||||
/* related to Sonera/Finland network */
|
||||
get_and_print_settings("244", "91", NULL);
|
||||
get_and_print_settings("244", "91", "sonera");
|
||||
get_and_print_settings("244", "91", "aina");
|
||||
|
||||
/* related to DNA/Finland network */
|
||||
get_and_print_settings("244", "03", NULL);
|
||||
get_and_print_settings("244", "03", "dna");
|
||||
get_and_print_settings("244", "03", "aina");
|
||||
get_and_print_settings("244", "04", NULL);
|
||||
get_and_print_settings("244", "04", "dna");
|
||||
get_and_print_settings("244", "04", "aina");
|
||||
|
||||
/* related to O2/UK network */
|
||||
get_and_print_settings("234", "10", NULL);
|
||||
get_and_print_settings("234", "10", "o2");
|
||||
get_and_print_settings("234", "10", "tesco");
|
||||
get_and_print_settings("234", "10", "giffgaff");
|
||||
|
||||
/* related to E-Plus/Germany network */
|
||||
get_and_print_settings("262", "03", NULL);
|
||||
get_and_print_settings("262", "03", "E-Plus");
|
||||
get_and_print_settings("262", "03", "simyo");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func("/testprovision/get_settings", test_get_settings);
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -345,12 +345,21 @@ const unsigned char valid_efopl[] = {
|
||||
};
|
||||
|
||||
const unsigned char valid_efpnn[][28] = {
|
||||
{ 0x43, 0x0a, 0x00, 0x54, 0x75, 0x78, 0x20, 0x43, 0x6f, 0x6d,
|
||||
0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, },
|
||||
{ 0x43, 0x08, 0x00, 0xD4, 0x3A, 0x1E, 0x34, 0x7C, 0xB7, 0xDB,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, },
|
||||
{ 0x43, 0x05, 0x00, 0x4C, 0x6F, 0x6E, 0x67, 0x45, 0x06, 0x00,
|
||||
0x53, 0x68, 0x6F, 0x72, 0x74, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
|
||||
};
|
||||
|
||||
const unsigned char valid_efpnn_2[][28] = {
|
||||
/* Solavei */
|
||||
{ 0x43, 0x08, 0x87, 0xD3, 0x37, 0x3B, 0x6C, 0x2F, 0xA7, 0x01 },
|
||||
/* T-Mobile / T-Mobile */
|
||||
{ 0x43, 0x08, 0x80, 0xD4, 0x56, 0xF3, 0x2D, 0x4E, 0xB3, 0xCB,
|
||||
0x45, 0x08, 0x80, 0xD4, 0x56, 0xF3, 0x2D, 0x4E, 0xB3, 0xCB,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||
};
|
||||
|
||||
static void test_eons(void)
|
||||
{
|
||||
const struct sim_eons_operator_info *op_info;
|
||||
@@ -360,6 +369,7 @@ static void test_eons(void)
|
||||
|
||||
g_assert(sim_eons_pnn_is_empty(eons_info));
|
||||
|
||||
/* 1. a fictious operator */
|
||||
sim_eons_add_pnn_record(eons_info, 1,
|
||||
valid_efpnn[0], sizeof(valid_efpnn[0]));
|
||||
g_assert(!sim_eons_pnn_is_empty(eons_info));
|
||||
@@ -380,6 +390,27 @@ static void test_eons(void)
|
||||
g_assert(!op_info->shortname);
|
||||
g_assert(!op_info->info);
|
||||
|
||||
/* 2. a real-world MVNO */
|
||||
sim_eons_add_pnn_record(eons_info, 1,
|
||||
valid_efpnn_2[0], sizeof(valid_efpnn_2[0]));
|
||||
g_assert(!sim_eons_pnn_is_empty(eons_info));
|
||||
|
||||
sim_eons_add_pnn_record(eons_info, 2,
|
||||
valid_efpnn_2[1], sizeof(valid_efpnn_2[1]));
|
||||
g_assert(!sim_eons_pnn_is_empty(eons_info));
|
||||
|
||||
sim_eons_add_opl_record(eons_info, valid_efopl, sizeof(valid_efopl));
|
||||
sim_eons_optimize(eons_info);
|
||||
|
||||
op_info = sim_eons_lookup(eons_info, "246", "82");
|
||||
g_assert(op_info == NULL);
|
||||
op_info = sim_eons_lookup(eons_info, "246", "81");
|
||||
g_assert(op_info);
|
||||
|
||||
g_assert(!strcmp(op_info->longname, "Solavei"));
|
||||
g_assert(!op_info->shortname);
|
||||
g_assert(!op_info->info);
|
||||
|
||||
sim_eons_free(eons_info);
|
||||
}
|
||||
|
||||
|
||||
@@ -1769,6 +1769,63 @@ static void test_wap_push(gconstpointer data)
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
static const char *simple_deliver_unicode = "0791534850020290"
|
||||
"040c915348608475840008412060610141800e0054006500730074002062116211";
|
||||
|
||||
static const char *simple_deliver_unicode_surrogate = "0791534850020290"
|
||||
"040c915348608475840008412060610141800e00540065007300740020D83DDE3B";
|
||||
|
||||
static void test_decode_unicode(void)
|
||||
{
|
||||
struct sms sms;
|
||||
unsigned char *pdu;
|
||||
long pdu_len;
|
||||
gboolean ret;
|
||||
struct sms_assembly *assembly;
|
||||
GSList *l;
|
||||
char *decoded;
|
||||
|
||||
/* contains UCS-2 (Chinese characters) */
|
||||
pdu = decode_hex(simple_deliver_unicode, -1, &pdu_len, 0);
|
||||
g_assert(pdu);
|
||||
g_assert(pdu_len == (long)strlen(simple_deliver_unicode) / 2);
|
||||
ret = sms_decode(pdu, pdu_len, FALSE, 33, &sms);
|
||||
g_free(pdu);
|
||||
|
||||
g_assert(ret);
|
||||
g_assert(sms.type == SMS_TYPE_DELIVER);
|
||||
g_assert(sms.deliver.udl == 14);
|
||||
|
||||
assembly = sms_assembly_new(NULL);
|
||||
l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
|
||||
&sms.deliver.oaddr, 0, 1, 0);
|
||||
g_assert(l);
|
||||
g_assert(g_slist_length(l) == 1);
|
||||
decoded = sms_decode_text(l);
|
||||
sms_assembly_free(assembly);
|
||||
g_assert(strcmp(decoded, "Test 我我") == 0);
|
||||
|
||||
/* contains UTF-16 (a Unicode surrogate pair representing an emoticon) */
|
||||
pdu = decode_hex(simple_deliver_unicode_surrogate, -1, &pdu_len, 0);
|
||||
g_assert(pdu);
|
||||
g_assert(pdu_len == (long)strlen(simple_deliver_unicode_surrogate) / 2);
|
||||
ret = sms_decode(pdu, pdu_len, FALSE, 33, &sms);
|
||||
g_free(pdu);
|
||||
|
||||
g_assert(ret);
|
||||
g_assert(sms.type == SMS_TYPE_DELIVER);
|
||||
g_assert(sms.deliver.udl == 14);
|
||||
|
||||
assembly = sms_assembly_new(NULL);
|
||||
l = sms_assembly_add_fragment(assembly, &sms, time(NULL),
|
||||
&sms.deliver.oaddr, 0, 1, 0);
|
||||
g_assert(l);
|
||||
g_assert(g_slist_length(l) == 1);
|
||||
decoded = sms_decode_text(l);
|
||||
sms_assembly_free(assembly);
|
||||
g_assert(strcmp(decoded, "Test 😻") == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char long_string[152*33 + 1];
|
||||
@@ -1850,5 +1907,7 @@ int main(int argc, char **argv)
|
||||
g_test_add_data_func("/testsms/Test WAP Push 1", &wap_push_1,
|
||||
test_wap_push);
|
||||
|
||||
g_test_add_func("/testsms/Test Decode Unicode", test_decode_unicode);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
@@ -71,6 +71,10 @@ autoreconf --force --install
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
|
||||
%check
|
||||
# run unit tests
|
||||
make check
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
@@ -97,7 +101,7 @@ systemctl daemon-reload ||:
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc COPYING ChangeLog AUTHORS README
|
||||
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/*.conf
|
||||
%config %{_sysconfdir}/dbus-1/system.d/*.conf
|
||||
%{_sbindir}/*
|
||||
/%{_lib}/systemd/system/network.target.wants/ofono.service
|
||||
/%{_lib}/systemd/system/ofono.service
|
||||
|
||||
Reference in New Issue
Block a user