Compare commits

...

28 Commits

Author SHA1 Message Date
Martti Piirainen
5c53260938 Merge pull request #213 from marttipiirainen/mbpi3
Take Service Provider Name into account in MBPI provisioning
2014-04-22 15:11:36 +03:00
Martti Piirainen
e3e691fb48 Merge pull request #214 from marttipiirainen/ringback
[voicecall] Inform client when local ringback tone is needed
2014-04-22 13:54:13 +03:00
Martti Piirainen
8fa99a07e8 [provision] Take SPN into account when finding APNs 2014-04-17 08:14:08 +03:00
Slava Monich
23f92a5b3e [mbpi] Parse gsm provider name 2014-04-17 07:32:36 +03:00
Slava Monich
94494f3a63 [provision] Fixed memory leak 2014-04-16 16:07:40 +03:00
Martti Piirainen
098b3d4a64 [unit] Add provisioning tests 2014-04-16 16:07:29 +03:00
Martti Piirainen
cfeb58f2a8 [provision] Expose provision_get_settings() in header (for testability) 2014-04-16 16:07:21 +03:00
Martti Piirainen
5f821b4a9a [voicecall] Inform client when local ringback tone is needed
In some networks, MO calls do not get the "alerting" tone in-band, so the device needs to play one locally.

This commit adds a "voice call agent" API. It currently contains only the ringback tone notification, but can be extended later.
2014-04-16 15:31:45 +03:00
Martti Piirainen
533d248288 Merge pull request #210 from nemomobile-packages/next
Merge various improvements from 'next' to 'master'
2014-04-08 10:54:18 +03:00
Martti Piirainen
4f512b6e56 Merge pull request #209 from jpoutiai/next
[RILMODEM] fix cf query callback list handling
2014-04-07 10:18:48 +03:00
Martti Piirainen
ce3a5e5a0b Merge pull request #204 from monich/ril_delayed_register
[rilmodem] Actually remove delayed register timer
2014-04-07 10:13:28 +03:00
Martti Piirainen
c97ef76c93 Merge pull request #205 from monich/ril_oemraw_delayed_register
[rilmodem] Remove delayed register timer in ril_oemraw_remove
2014-04-07 10:13:11 +03:00
Jarko Poutiainen
95659d7c49 [RILMODEM] fix cf query callback list handling
Signed-off-by: Jarko Poutiainen <Jarko.Poutiainen@oss.tieto.com>
2014-04-04 15:03:08 +03:00
Tommi Kenakkala
eb986f49e4 Merge pull request #208 from tkenakka/next
[ofono][dundee] At startup order dundee after dbus instead of syslog.
2014-04-01 15:27:26 +03:00
Tommi Kenakkala
4691d385c0 [ofono][dundee] At startup order dundee after dbus instead of syslog.
According to systemd documentation
"Newer systemd versions (v35+) do not support non-socket-activated syslog
daemons anymore and we do no longer recommend people to order their units
after syslog.target."

Signed-off-by: Tommi Kenakkala <tommi.kenakkala@oss.tieto.com>
2014-04-01 13:15:53 +03:00
Martti Piirainen
0ddebfea70 Merge pull request #207 from tkenakka/nwlock
[rilmodem] Network lock depersonalisation support
2014-03-31 07:12:49 +03:00
Tommi Kenakkala
2d1f2b0650 [rilmodem] Network lock depersonalisation support
Signed-off-by: Tommi Kenakkala <tommi.kenakkala@oss.tieto.com>
2014-03-28 13:52:56 +02:00
Martti Piirainen
0ca5c87999 Merge pull request #206 from marttipiirainen/voice_busy
[rilmodem] Fine-tune disconnect reasons for MO calls
2014-03-28 12:33:58 +02:00
Martti Piirainen
e3dcd67a1b [rilmodem] Fine-tune disconnect reasons for MO calls 2014-03-28 08:04:23 +02:00
Slava Monich
99b9099082 [rilmodem] Remove delayed register timer in ril_oemraw_remove 2014-03-27 16:42:22 +02:00
Slava Monich
ec74da107d [rilmodem] Actually remove delayed register timer in ril_call_barring_remove 2014-03-27 16:33:47 +02:00
Jarko Poutiainen
50f146939f Merge pull request #203 from tkenakka/next
[rilmodem] Minor rilmodem/sim.c mem leak fix
2014-03-27 11:06:56 +02:00
Tommi Kenakkala
e7a07b4694 [rilmodem] Minor rilmodem/sim.c mem leak fix
Signed-off-by: Tommi Kenakkala <tommi.kenakkala@oss.tieto.com>
2014-03-27 10:58:32 +02:00
Martti Piirainen
461d18f4a3 Merge pull request #195 from marttipiirainen/unit
Unit test improvements
2014-03-26 13:07:47 +02:00
Jussi Kangas
16ea57247d [rilmodem] Check if really network registration status is really searching
If connection drops to searching and only voice call registration
status changes to roaming, with current implementation it is possible
to get through roaming allowed check in core. This prevents it.

Signed-off-by: Jussi Kangas <jussi.kangas@oss.tieto.com>
2014-03-26 10:56:22 +02:00
Martti Piirainen
88f42f44c1 [unit] SMS decoding tests for Unicode 2014-03-14 09:05:22 +02:00
Martti Piirainen
2aed3c3f66 [unit] Fix EF_PNN unit test
Correct the encoding of the existing test case, and add a second test (the latter is based on Canonical rilmodem code).
2014-03-14 09:05:22 +02:00
Martti Piirainen
9c9028b164 [rpm] Run unit tests before creating .rpm 2014-03-14 09:05:22 +02:00
25 changed files with 855 additions and 79 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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.
*

View File

@@ -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);

View File

@@ -1,6 +1,7 @@
[Unit]
Description=DUN service
After=syslog.target
Requires=dbus.service
After=dbus.service
[Service]
Type=dbus

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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
View 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);

View File

@@ -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">

View File

@@ -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
View 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;
}

View 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
View 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)"

View 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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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