Compare commits

...

12 Commits

Author SHA1 Message Date
Slava Monich
44f5f8f474 Merge pull request #34 from monich/ims-4.4.0
Cherry-pick IMS changes from master
2022-05-10 13:24:21 +03:00
Slava Monich
fe1e9ce9c9 [ims] Disable IMS registration by default 2022-05-09 19:05:14 +03:00
Slava Monich
e4fc0626c1 [ims] Tweak the treatment of the default Registration value
To handle the case if it's not IMS_REG_AUTO
2022-05-09 19:03:17 +03:00
Slava Monich
08ce5308cf [ims] Extend org.ofono.IpMultimediaSystem D-Bus API. JB#57999
The following property has been added to the API:

	string Registration [readwrite, Sailfish OS specific]

		The IMS registration strategy. Valid values are:

			"disabled" keep registration off
			"enabled"  manual registration
			"auto"     keep registration on

		The Register() method, if implemented, will fail
		with [service].Error.NotAllowed if the value of
		this property is "disabled".
2022-05-09 19:03:17 +03:00
Slava Monich
b680de231d [watch] Added reg_tech watch. JB#57999 2022-05-09 19:03:17 +03:00
Slava Monich
fe85fbbd70 [ims] D-Bus access control for org.ofono.IpMultimediaSystem. JB#57408 2022-05-09 19:03:17 +03:00
Slava Monich
c52151b8c9 [dbus-access] Added access control entry for SendDataMessage. JB#56657 2022-03-14 10:52:04 +02:00
Slava Monich
88378c4c77 Housekeeping 2022-03-14 10:52:04 +02:00
Jussi Laakkonen
8a9c0ab853 [sms] Support setting endianess for SMS data messages. JB#56657
This implements support for selecting endianess for the SMS data message
multi-byte parameters. By default big endian is used but little endian
is required in some special protocols. Thus, omitting flag value results
in the "GSM" setting which is the big endian used by default.

This required adding a new sms_datagram_prepare_with_endianess() plugin
API call that is called by the original sms_datagram_prepare() with GSM
encoding.

This affects only the new SendDataMessage D-Bus API. A value 0x02 for
little endian is added to enum ofono_sms_data_flag().
2022-03-14 10:52:04 +02:00
Jussi Laakkonen
a994a95186 [sms] Add support for sending SMS data messages. Fixes JB#56657
This adds a new D-Bus API call "SendDataMessage" to be used for sending
a SMS data message. This is required especially by AML but can be
utilized for other uses as well.

The given message data is defined as a byte array so pre-encoded data
is only supported. Additionally source and destination ports as well as
flags are to be defined for the SMS data message. Flag
OFONO_SMS_DATA_FLAG_DELIVERY_REPORT (0x01) determine the need for
delivery reports. Other flags may be added later on.

This also implements the filter functionality for the SMS data messages.
This can be utilized by the plugins to react to the sent SMS data
messages appropriately.
2022-03-14 10:52:04 +02:00
Jussi Laakkonen
aec8bdd69d [voicecall] Allow filtering for emergency calls. JB#56657
This removes the exceptions made for emergency calls to disallow
filtering of them via plugins. Thus, this allows the plugins to detect
if an emergency call is made and make an action based on it.
2022-03-14 10:52:04 +02:00
Slava Monich
bdf046094f [ofono] Added API for querying IMEI from the modem. JB#56657
ofono_devinfo_get_serial(ofono_modem_get_devinfo(modem))
2022-03-14 10:52:04 +02:00
19 changed files with 1042 additions and 144 deletions

View File

@@ -16,7 +16,7 @@ Methods dict GetProperties()
changeable. On success a PropertyChanged signal
will be emitted.
Possible Errors: [service].Error.InProgress
Possible Errors: [service].Error.AccessDenied
[service].Error.InvalidArguments
[service].Error.Failed
@@ -27,8 +27,10 @@ Methods dict GetProperties()
initiated successfully. The actual registration state
will be reflected by the 'Registered' property.
Possible Errors: [service].Error.InProgress
Possible Errors: [service].Error.AccessDenied
[service].Error.NotAllowed
[service].Error.NotImplemented
[service].Error.Failed
void Unregister()
@@ -37,8 +39,9 @@ Methods dict GetProperties()
be initiated successfully. The actual unregistration
state will be reflected by the 'Registered' property.
Possible Errors: [service].Error.InProgress
Possible Errors: [service].Error.AccessDenied
[service].Error.NotImplemented
[service].Error.Failed
Signals PropertyChanged(string property, variant value)
@@ -57,3 +60,15 @@ Properties boolean Registered [readonly]
boolean SmsCapable [readonly, optional]
Boolean representing whether SMS-over-IMS is available.
string Registration [readwrite, Sailfish OS specific]
The IMS registration strategy. Valid values are:
"disabled" keep registration off
"enabled" manual registration
"auto" keep registration on
The Register() method, if implemented, will fail
with [service].Error.NotAllowed if the value of
this property is "disabled".

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019-2021 Jolla Ltd.
* Copyright (C) 2019-2022 Jolla Ltd.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -41,6 +41,8 @@ enum ofono_dbus_access_intf {
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS, /* org.ofono.RadioSettings */
OFONO_DBUS_ACCESS_INTF_STK, /* org.ofono.SimToolkit */
OFONO_DBUS_ACCESS_INTF_OEMRAW, /* org.ofono.OemRaw */
/* Since 1.29+git3 */
OFONO_DBUS_ACCESS_INTF_IMS, /* org.ofono.IpMultimediaSystem */
OFONO_DBUS_ACCESS_INTF_COUNT
};
@@ -53,6 +55,7 @@ enum ofono_dbus_access_message_method {
/* OFONO_DBUS_ACCESS_INTF_MESSAGEMGR */
enum ofono_dbus_access_messagemgr_method {
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE,
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE, /* Since 1.28+git5 */
OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT
};
@@ -131,6 +134,15 @@ enum ofono_dbus_access_oemraw_method {
OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_IMS */
enum ofono_dbus_access_ims_method {
/* Since 1.29+git3 */
OFONO_DBUS_ACCESS_IMS_SET_PROPERTY,
OFONO_DBUS_ACCESS_IMS_REGISTER,
OFONO_DBUS_ACCESS_IMS_UNREGISTER,
OFONO_DBUS_ACCESS_IMS_METHOD_COUNT
};
#define OFONO_DBUS_ACCESS_PRIORITY_LOW (-100)
#define OFONO_DBUS_ACCESS_PRIORITY_DEFAULT (0)
#define OFONO_DBUS_ACCESS_PRIORITY_HIGH (100)
@@ -158,7 +170,7 @@ const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf);
const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
int method);
/* Since mer/1.24+git2 */
/* Since 1.24+git2 */
ofono_bool_t ofono_dbus_access_method_allowed(const char *sender,
enum ofono_dbus_access_intf iface, int method, const char *arg);

View File

@@ -3,6 +3,7 @@
* oFono - Open Telephony stack for Linux
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2022 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
@@ -65,6 +66,9 @@ void *ofono_devinfo_get_data(struct ofono_devinfo *info);
struct ofono_modem *ofono_devinfo_get_modem(struct ofono_devinfo *info);
/* Since 1.28+git4 */
const char *ofono_devinfo_get_serial(struct ofono_devinfo *info);
#ifdef __cplusplus
}
#endif

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2015-2022 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
@@ -29,6 +29,7 @@ extern "C" {
#include <ofono/types.h>
struct ofono_devinfo;
struct ofono_modem;
struct ofono_gprs;
struct ofono_sim;
@@ -92,7 +93,9 @@ struct ofono_gprs *ofono_modem_get_gprs(struct ofono_modem *modem);
struct ofono_voicecall *ofono_modem_get_voicecall(struct ofono_modem *modem);
struct ofono_netreg *ofono_modem_get_netreg(struct ofono_modem *modem);
struct ofono_radio_settings *ofono_modem_get_radio_settings
(struct ofono_modem *modem); /* Since mer/1.24+git2 */
(struct ofono_modem *modem); /* Since 1.24+git2 */
struct ofono_devinfo *ofono_modem_get_devinfo
(struct ofono_modem *modem); /* Since 1.28+git4 */
void ofono_modem_set_data(struct ofono_modem *modem, void *data);
void *ofono_modem_get_data(struct ofono_modem *modem);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2022 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
@@ -60,6 +61,11 @@ struct ofono_sms_driver {
ofono_sms_bearer_set_cb_t, void *data);
};
enum ofono_sms_data_flag {
OFONO_SMS_DATA_FLAG_DELIVERY_REPORT = 0x01,
OFONO_SMS_DATA_FLAG_USE_LITTLE_ENDIAN = 0x02
}; /* Since 1.28+git5 */
void ofono_sms_deliver_notify(struct ofono_sms *sms, const unsigned char *pdu,
int len, int tpdu_len);
void ofono_sms_status_notify(struct ofono_sms *sms, const unsigned char *pdu,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2021 Jolla Ltd.
* Copyright (C) 2017-2022 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
@@ -36,13 +36,15 @@ struct ofono_watch {
const char *spn;
/* OFONO_ATOM_TYPE_NETREG */
struct ofono_netreg *netreg;
/* Since mer/1.21+git47 */
/* Since 1.21+git47 */
enum ofono_netreg_status reg_status;
const char *reg_mcc;
const char *reg_mnc;
const char *reg_name;
/* OFONO_ATOM_TYPE_GPRS */
struct ofono_gprs *gprs;
/* Since 1.29+git3 */
enum ofono_access_technology reg_tech;
};
typedef void (*ofono_watch_cb_t)(struct ofono_watch *w, void *user_data);
@@ -78,7 +80,7 @@ void ofono_watch_remove_handlers(struct ofono_watch *w, unsigned long *ids,
#define ofono_watch_remove_all_handlers(w,ids) \
ofono_watch_remove_handlers(w, ids, sizeof(ids)/sizeof((ids)[0]))
/* Since mer/1.21+git47 */
/* Since 1.21+git47 */
unsigned long ofono_watch_add_reg_status_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_reg_mcc_changed_handler(struct ofono_watch *w,
@@ -93,6 +95,10 @@ unsigned long ofono_watch_add_gprs_settings_changed_handler
(struct ofono_watch *watch, ofono_watch_gprs_settings_cb_t cb,
void *user_data);
/* Since 1.29+git3 */
unsigned long ofono_watch_add_reg_tech_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
#endif /* OFONO_WATCH_H */
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019-2021 Jolla Ltd.
* Copyright (C) 2019-2022 Jolla Ltd.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -46,6 +46,8 @@ const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf)
return OFONO_STK_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_OEMRAW:
return "org.ofono.OemRaw";
case OFONO_DBUS_ACCESS_INTF_IMS:
return OFONO_IMS_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}
@@ -68,6 +70,8 @@ const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
switch ((enum ofono_dbus_access_messagemgr_method)method) {
case OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE:
return "SendMessage";
case OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE:
return "SendDataMessage";
case OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT:
break;
}
@@ -186,6 +190,18 @@ const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_IMS:
switch ((enum ofono_dbus_access_ims_method)method) {
case OFONO_DBUS_ACCESS_IMS_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_IMS_REGISTER:
return "Register";
case OFONO_DBUS_ACCESS_IMS_UNREGISTER:
return "Unregister";
case OFONO_DBUS_ACCESS_IMS_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}

View File

@@ -36,21 +36,342 @@
#include "ofono.h"
#include "common.h"
#include "storage.h"
#include "dbus-queue.h"
#define VOICE_CAPABLE_FLAG OFONO_IMS_VOICE_CAPABLE
#define SMS_CAPABLE_FLAG OFONO_IMS_SMS_CAPABLE
#define RECHECK_TIMEOUT_SEC (10)
enum ims_reg_strategy {
IMS_REG_DISABLED,
IMS_REG_ENABLED,
IMS_REG_AUTO
#define IMS_REG_DEFAULT IMS_REG_DISABLED
};
enum ims_watch_events {
WATCH_EVENT_REG_TECH,
WATCH_EVENT_IMSI,
WATCH_EVENT_COUNT
};
struct ims_call;
struct ofono_ims {
int reg_info;
int ext_info;
const struct ofono_ims_driver *driver;
void *driver_data;
struct ofono_atom *atom;
DBusMessage *pending;
struct ofono_watch *watch;
struct ofono_dbus_queue *q;
struct ims_call *pending;
struct ims_call *tail;
enum ims_reg_strategy reg_strategy;
gboolean reg_check_pending;
gulong watch_id[WATCH_EVENT_COUNT];
char *imsi;
GKeyFile *settings;
guint recheck_timeout_id;
};
/* Calls to the driver are serialized */
typedef void (*ims_cb_t)(void);
typedef void (*ims_submit_cb_t)(struct ims_call *call);
struct ims_call {
struct ims_call *next;
struct ofono_ims *ims;
ims_submit_cb_t submit;
union {
ofono_ims_register_cb_t register_cb;
ofono_ims_status_cb_t status_cb;
ims_cb_t fn;
} cb;
void *data;
};
#define CALLBACK(f) ((ims_cb_t)(f))
#define REGISTRATION_PROP "Registration"
#define SETTINGS_STORE "ims"
#define SETTINGS_GROUP "Settings"
#define REGISTRATION_KEY REGISTRATION_PROP
static GSList *g_drivers = NULL;
static const char *reg_strategy_name[] = { "disabled", "enabled", "auto" };
static gboolean ims_registration_recheck_cb(gpointer user_data);
static gboolean ims_ret_strategy_from_string(const char *str,
enum ims_reg_strategy *value)
{
if (str) {
int i;
for (i = 0; i < G_N_ELEMENTS(reg_strategy_name); i++) {
if (!g_strcmp0(str, reg_strategy_name[i])) {
*value = i;
return TRUE;
}
}
}
return FALSE;
}
static inline gboolean ims_dbus_access_allowed(DBusMessage *msg,
enum ofono_dbus_access_ims_method method)
{
return ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_IMS, method, NULL);
}
static void ims_call_done(struct ims_call *call)
{
struct ofono_ims *ims = call->ims;
ims->pending = call->next;
g_slice_free(struct ims_call, call);
if (ims->pending) {
ims->pending->submit(ims->pending);
} else {
ims->tail = NULL;
}
}
static void ims_call_submit(struct ofono_ims *ims, ims_submit_cb_t submit,
ims_cb_t cb, void *data)
{
struct ims_call *call = g_slice_new0(struct ims_call);
call->ims = ims;
call->submit = submit;
call->cb.fn = cb;
call->data = data;
if (ims->pending) {
ims->tail->next = call;
ims->tail = call;
} else {
ims->pending = ims->tail = call;
submit(call);
}
}
static void ims_call_register_cb(const struct ofono_error *error, void *data)
{
struct ims_call *call = data;
if (call->cb.register_cb)
call->cb.register_cb(error, call->data);
ims_call_done(call);
}
static void ims_call_status_cb(const struct ofono_error *error,
int reg_info, int ext_info,
void *data)
{
struct ims_call *call = data;
if (call->cb.status_cb)
call->cb.status_cb(error, reg_info, ext_info, call->data);
ims_call_done(call);
}
static void ims_call_submit_registration_status(struct ims_call *call)
{
struct ofono_ims *ims = call->ims;
ims->driver->registration_status(ims, ims_call_status_cb, call);
}
static void ims_call_submit_register(struct ims_call *call)
{
struct ofono_ims *ims = call->ims;
ims->driver->ims_register(ims, ims_call_register_cb, call);
}
static void ims_call_submit_unregister(struct ims_call *call)
{
struct ofono_ims *ims = call->ims;
ims->driver->ims_unregister(ims, ims_call_register_cb, call);
}
static void ims_call_registration_status(struct ofono_ims *ims,
ofono_ims_status_cb_t cb, void *data)
{
ims_call_submit(ims, ims_call_submit_registration_status,
CALLBACK(cb), data);
}
static void ims_call_register(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data)
{
ims_call_submit(ims, ims_call_submit_register, CALLBACK(cb), data);
}
static void ims_call_unregister(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data)
{
ims_call_submit(ims, ims_call_submit_unregister, CALLBACK(cb), data);
}
static gboolean ims_supported_reg_tech(struct ofono_ims *ims)
{
return ims->watch &&
ims->watch->reg_tech >= OFONO_ACCESS_TECHNOLOGY_EUTRAN;
}
static void ims_registration_check(struct ofono_ims *ims)
{
if (!ims->reg_check_pending)
return;
ims->reg_check_pending = FALSE;
if (ims->recheck_timeout_id) {
g_source_remove(ims->recheck_timeout_id);
ims->recheck_timeout_id = 0;
}
DBG("checking ims state");
switch (ims->reg_strategy) {
case IMS_REG_DISABLED:
/* Keep registration off */
if (ims->reg_info && ims->driver &&
ims->driver->ims_unregister) {
DBG("auto-unregistering");
ims_call_unregister(ims, NULL, NULL);
ims->recheck_timeout_id =
g_timeout_add_seconds(RECHECK_TIMEOUT_SEC,
ims_registration_recheck_cb, ims);
} else {
DBG("ims is disabled, leaving it unregistered");
}
return;
case IMS_REG_ENABLED:
/* Any state is acceptable */
DBG("ims is enabled, no action needed");
return;
case IMS_REG_AUTO:
break;
}
/* Keep registration on (default behavior) */
if (!ims->reg_info && ims_supported_reg_tech(ims) &&
ims->driver && ims->driver->ims_register) {
DBG("auto-registering");
ims_call_register(ims, NULL, NULL);
ims->recheck_timeout_id =
g_timeout_add_seconds(RECHECK_TIMEOUT_SEC,
ims_registration_recheck_cb, ims);
} else {
DBG("leaving ims registered");
}
}
static gboolean ims_registration_recheck_cb(gpointer user_data)
{
struct ofono_ims *ims = user_data;
ims->recheck_timeout_id = 0;
ims_registration_check(ims);
return G_SOURCE_REMOVE;
}
static void ims_reg_tech_changed(struct ofono_watch *watch, void *data)
{
struct ofono_ims *ims = data;
ims->reg_check_pending = TRUE;
ims_registration_check(ims);
}
static void ims_set_reg_strategy(struct ofono_ims *ims,
enum ims_reg_strategy value)
{
if (ims->reg_strategy != value) {
const char *path = __ofono_atom_get_path(ims->atom);
DBusConnection *conn = ofono_dbus_get_connection();
DBG("ims %s", reg_strategy_name[value]);
ims->reg_strategy = value;
ims->reg_check_pending = TRUE;
if (ims->settings) {
g_key_file_set_string(ims->settings, SETTINGS_GROUP,
REGISTRATION_KEY, reg_strategy_name[value]);
storage_sync(ims->imsi, SETTINGS_STORE, ims->settings);
}
ofono_dbus_signal_property_changed(conn, path,
OFONO_IMS_INTERFACE,
REGISTRATION_PROP, DBUS_TYPE_STRING,
reg_strategy_name + ims->reg_strategy);
}
}
static gboolean ims_imsi_check(struct ofono_ims *ims)
{
const char* imsi = ims->watch ? ims->watch->imsi : NULL;
if (g_strcmp0(ims->imsi, imsi)) {
if (ims->imsi) {
storage_close(ims->imsi, SETTINGS_STORE,
ims->settings, TRUE);
g_free(ims->imsi);
}
if (imsi) {
ims->settings = storage_open(imsi, SETTINGS_STORE);
ims->imsi = g_strdup(imsi);
} else {
ims->settings = NULL;
ims->imsi = NULL;
}
return TRUE;
}
return FALSE;
}
static void ims_apply_settings(struct ofono_ims *ims)
{
char* str;
if (!ims->settings)
return;
str = g_key_file_get_string(ims->settings, SETTINGS_GROUP,
REGISTRATION_KEY, NULL);
if (str) {
enum ims_reg_strategy ims_reg = IMS_REG_DEFAULT;
if (ims_ret_strategy_from_string(str, &ims_reg))
ims_set_reg_strategy(ims, ims_reg);
g_free(str);
}
}
static void ims_imsi_changed(struct ofono_watch *watch, void *data)
{
struct ofono_ims *ims = data;
if (ims_imsi_check(ims)) {
ims_apply_settings(ims);
ims_registration_check(ims);
}
}
static DBusMessage *ims_get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -72,6 +393,8 @@ static DBusMessage *ims_get_properties(DBusConnection *conn,
value = ims->reg_info ? TRUE : FALSE;
ofono_dbus_dict_append(&dict, "Registered", DBUS_TYPE_BOOLEAN, &value);
ofono_dbus_dict_append(&dict, REGISTRATION_PROP, DBUS_TYPE_STRING,
reg_strategy_name + ims->reg_strategy);
if (ims->ext_info != -1) {
value = ims->ext_info & VOICE_CAPABLE_FLAG ? TRUE : FALSE;
@@ -88,6 +411,50 @@ static DBusMessage *ims_get_properties(DBusConnection *conn,
return reply;
}
static DBusMessage *ims_set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_ims *ims = data;
DBusMessageIter iter;
DBusMessageIter var;
const char *property;
if (!ims_dbus_access_allowed(msg, OFONO_DBUS_ACCESS_IMS_SET_PROPERTY))
return __ofono_error_access_denied(msg);
if (!dbus_message_iter_init(msg, &iter))
return __ofono_error_invalid_args(msg);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&iter, &property);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
dbus_message_iter_recurse(&iter, &var);
if (!g_strcmp0(property, REGISTRATION_PROP)) {
const char *str = NULL;
enum ims_reg_strategy value = IMS_REG_DEFAULT;
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &str);
if (ims_ret_strategy_from_string(str, &value)) {
ims_set_reg_strategy(ims, value);
ims_registration_check(ims);
return dbus_message_new_method_return(msg);
}
}
return __ofono_error_invalid_args(msg);
}
static void ims_set_sms_capable(struct ofono_ims *ims, ofono_bool_t status)
{
const char *path = __ofono_atom_get_path(ims->atom);
@@ -155,6 +522,7 @@ void ofono_ims_status_notify(struct ofono_ims *ims, int reg_info, int ext_info)
if (ims->ext_info == ext_info && ims->reg_info == reg_info)
return;
ims->reg_check_pending = TRUE;
new_reg_info = reg_info ? TRUE : FALSE;
ims_set_registered(ims, new_reg_info);
@@ -170,38 +538,26 @@ void ofono_ims_status_notify(struct ofono_ims *ims, int reg_info, int ext_info)
skip:
ims->reg_info = reg_info;
ims->ext_info = ext_info;
}
static void registration_status_cb(const struct ofono_error *error,
int reg_info, int ext_info,
void *data)
{
struct ofono_ims *ims = data;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Error during IMS registration/unregistration");
return;
}
ofono_ims_status_notify(ims, reg_info, ext_info);
ims_registration_check(ims);
}
static void register_cb(const struct ofono_error *error, void *data)
{
struct ofono_ims *ims = data;
DBusMessage *reply;
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
reply = dbus_message_new_method_return(ims->pending);
__ofono_dbus_queue_reply_ok(ims->q);
else
reply = __ofono_error_failed(ims->pending);
__ofono_dbus_queue_reply_failed(ims->q);
}
__ofono_dbus_pending_reply(&ims->pending, reply);
static DBusMessage *ofono_ims_register_fn(DBusMessage *msg, void *data)
{
struct ofono_ims *ims = data;
if (ims->driver->registration_status == NULL)
return;
ims_call_register(ims, register_cb, ims);
ims->driver->registration_status(ims, registration_status_cb, ims);
return NULL;
}
static DBusMessage *ofono_ims_send_register(DBusConnection *conn,
@@ -209,15 +565,25 @@ static DBusMessage *ofono_ims_send_register(DBusConnection *conn,
{
struct ofono_ims *ims = data;
if (ims->pending)
return __ofono_error_busy(msg);
if (!ims_dbus_access_allowed(msg, OFONO_DBUS_ACCESS_IMS_REGISTER))
return __ofono_error_access_denied(msg);
if (ims->driver->ims_register == NULL)
if (!ims->driver || !ims->driver->ims_register)
return __ofono_error_not_implemented(msg);
ims->pending = dbus_message_ref(msg);
if (ims->reg_strategy == IMS_REG_DISABLED)
return __ofono_error_not_allowed(msg);
ims->driver->ims_register(ims, register_cb, ims);
__ofono_dbus_queue_request(ims->q, ofono_ims_register_fn, msg, ims);
return NULL;
}
static DBusMessage *ofono_ims_unregister_fn(DBusMessage *msg, void *data)
{
struct ofono_ims *ims = data;
ims_call_unregister(ims, register_cb, ims);
return NULL;
}
@@ -227,15 +593,13 @@ static DBusMessage *ofono_ims_unregister(DBusConnection *conn,
{
struct ofono_ims *ims = data;
if (ims->pending)
return __ofono_error_busy(msg);
if (!ims_dbus_access_allowed(msg, OFONO_DBUS_ACCESS_IMS_UNREGISTER))
return __ofono_error_access_denied(msg);
if (ims->driver->ims_unregister == NULL)
if (!ims->driver || !ims->driver->ims_unregister)
return __ofono_error_not_implemented(msg);
ims->pending = dbus_message_ref(msg);
ims->driver->ims_unregister(ims, register_cb, ims);
__ofono_dbus_queue_request(ims->q, ofono_ims_unregister_fn, msg, ims);
return NULL;
}
@@ -244,6 +608,9 @@ static const GDBusMethodTable ims_methods[] = {
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
ims_get_properties) },
{ GDBUS_METHOD("SetProperty",
GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
NULL, ims_set_property) },
{ GDBUS_ASYNC_METHOD("Register", NULL, NULL,
ofono_ims_send_register) },
{ GDBUS_ASYNC_METHOD("Unregister", NULL, NULL,
@@ -269,6 +636,25 @@ static void ims_atom_remove(struct ofono_atom *atom)
if (ims->driver && ims->driver->remove)
ims->driver->remove(ims);
while (ims->pending) {
struct ims_call *call = ims->pending;
ims->pending = call->next;
g_slice_free(struct ims_call, call);
}
if (ims->imsi) {
storage_close(ims->imsi, SETTINGS_STORE, ims->settings, TRUE);
g_free(ims->imsi);
}
if (ims->recheck_timeout_id) {
g_source_remove(ims->recheck_timeout_id);
}
__ofono_dbus_queue_free(ims->q);
ofono_watch_remove_all_handlers(ims->watch, ims->watch_id);
ofono_watch_unref(ims->watch);
g_free(ims);
}
@@ -291,6 +677,9 @@ struct ofono_ims *ofono_ims_create(struct ofono_modem *modem,
ims->reg_info = 0;
ims->ext_info = -1;
ims->reg_strategy = IMS_REG_DEFAULT;
ims->reg_check_pending = TRUE;
ims->q = __ofono_dbus_queue_new();
for (l = g_drivers; l; l = l->next) {
const struct ofono_ims_driver *drv = l->data;
@@ -354,8 +743,21 @@ static void ofono_ims_finish_register(struct ofono_ims *ims)
return;
}
ims->watch = ofono_watch_new(path);
ims->watch_id[WATCH_EVENT_REG_TECH] =
ofono_watch_add_reg_tech_changed_handler(ims->watch,
ims_reg_tech_changed, ims);
ims->watch_id[WATCH_EVENT_IMSI] =
ofono_watch_add_imsi_changed_handler(ims->watch,
ims_imsi_changed, ims);
ofono_modem_add_interface(modem, OFONO_IMS_INTERFACE);
__ofono_atom_register(ims->atom, ims_atom_unregister);
ims->reg_check_pending = TRUE;
ims_imsi_check(ims);
ims_apply_settings(ims);
ims_registration_check(ims);
}
static void registration_init_cb(const struct ofono_error *error,
@@ -374,12 +776,12 @@ static void registration_init_cb(const struct ofono_error *error,
void ofono_ims_register(struct ofono_ims *ims)
{
if (!ims->driver->registration_status) {
if (!ims->driver || !ims->driver->registration_status) {
ofono_ims_finish_register(ims);
return;
}
ims->driver->registration_status(ims, registration_init_cb, ims);
ims_call_registration_status(ims, registration_init_cb, ims);
}
void ofono_ims_remove(struct ofono_ims *ims)

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2015-2022 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
@@ -2371,7 +2371,7 @@ out:
modem->emergency--;
}
/* Since mer/1.25+git2 */
/* Since 1.25+git2 */
unsigned int ofono_modem_add_watch(ofono_modemwatch_cb_t cb, void *user,
ofono_destroy_func destroy)
@@ -2383,3 +2383,15 @@ ofono_bool_t ofono_modem_remove_watch(unsigned int id)
{
return __ofono_modemwatch_remove(id);
}
/* Since 1.28+git4 */
struct ofono_devinfo *ofono_modem_get_devinfo(struct ofono_modem *modem)
{
return __ofono_atom_find(OFONO_ATOM_TYPE_DEVINFO, modem);
}
const char *ofono_devinfo_get_serial(struct ofono_devinfo *info)
{
return info ? info->serial : NULL;
}

View File

@@ -575,6 +575,9 @@ enum sms_class;
typedef void (*sms_send_text_cb_t)(struct ofono_sms *sms,
const struct sms_address *addr, const char *text, void *data);
typedef void (*sms_send_datagram_cb_t)(struct ofono_sms *sms,
const struct sms_address *addr, int dstport, int srcport,
unsigned char *bytes, unsigned int len, int flags, void *data);
typedef void (*sms_dispatch_recv_text_cb_t)
(struct ofono_sms *sms, const struct ofono_uuid *uuid,
@@ -594,6 +597,11 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
const struct sms_address *addr, const char *text,
sms_send_text_cb_t sender, ofono_destroy_func destroy,
void *data);
void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
const struct sms_address *addr, int dstport, int srcport,
unsigned char *bytes, int len, int flags,
sms_send_datagram_cb_t sender, ofono_destroy_func destroy,
void *data);
/* Does g_free(buf) when done */
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,

View File

@@ -85,6 +85,19 @@ struct sms_filter_chain_send_text {
struct ofono_sms_address addr;
};
struct sms_filter_chain_send_datagram {
struct sms_filter_message message;
sms_send_datagram_cb_t send;
ofono_destroy_func destroy;
void *data;
int dst_port;
int src_port;
unsigned char *bytes;
unsigned int len;
int flags;
struct ofono_sms_address addr;
};
struct sms_filter_chain_recv_text {
struct sms_filter_message message;
sms_dispatch_recv_text_cb_t default_handler;
@@ -445,6 +458,140 @@ static struct sms_filter_message *sms_filter_send_text_new
return &send_msg->message;
}
/* sms_filter_chain_send_datagram */
static inline struct sms_filter_chain_send_datagram
*sms_filter_chain_send_datagram_cast
(struct sms_filter_message *msg)
{
return CAST(msg, struct sms_filter_chain_send_datagram, message);
}
static gboolean sms_filter_chain_send_datagram_can_process
(const struct ofono_sms_filter *filter)
{
return filter->filter_send_datagram != NULL;
}
static void sms_datagram_set_bytes(
struct sms_filter_chain_send_datagram *msg,
const unsigned char *bytes, unsigned int len)
{
msg->bytes = g_malloc0(sizeof(unsigned char) * len);
memcpy(msg->bytes, bytes, len);
msg->len = len;
}
static void sms_filter_chain_send_datagram_process_cb
(enum ofono_sms_filter_result res,
const struct ofono_sms_address *addr,
int dst_port, int src_port,
const unsigned char *bytes,
unsigned int len, void *data)
{
struct sms_filter_chain_send_datagram *msg = data;
if (res != OFONO_SMS_FILTER_DROP) {
/* Update the message */
if (&msg->addr != addr) {
msg->addr = *addr;
}
if (msg->bytes != bytes) {
g_free(msg->bytes);
sms_datagram_set_bytes(msg, bytes, len);
}
msg->dst_port = dst_port;
msg->src_port = src_port;
}
sms_filter_message_processed(&msg->message, res);
}
static guint sms_filter_chain_send_datagram_process
(const struct ofono_sms_filter *filter,
struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);
struct sms_filter_chain *chain = msg->chain;
return filter->filter_send_datagram(chain->modem, &send_msg->addr,
send_msg->dst_port, send_msg->src_port,
send_msg->bytes, send_msg->len,
sms_filter_chain_send_datagram_process_cb,
send_msg);
}
static void sms_filter_chain_send_datagram_passthrough
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);
if (send_msg->send) {
struct sms_filter_chain *chain = msg->chain;
struct sms_address addr;
sms_filter_convert_sms_address_back(&addr, &send_msg->addr);
send_msg->send(chain->sms, &addr, send_msg->dst_port,
send_msg->src_port, send_msg->bytes,
send_msg->len, send_msg->flags,
send_msg->data);
}
}
static void sms_filter_chain_send_datagram_destroy
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);
if (send_msg->destroy) {
send_msg->destroy(send_msg->data);
}
}
static void sms_filter_chain_send_datagram_free
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);
g_free(send_msg->bytes);
g_free(send_msg);
}
static struct sms_filter_message *sms_filter_send_datagram_new
(struct sms_filter_chain *chain, const struct sms_address *addr,
int dst_port, int src_port, unsigned char *bytes,
unsigned int len, int flags, sms_send_datagram_cb_t send,
void *data, ofono_destroy_func destroy)
{
static const struct sms_filter_message_fn send_datagram_fn = {
.name = "outgoing SMS data message",
.can_process = sms_filter_chain_send_datagram_can_process,
.process = sms_filter_chain_send_datagram_process,
.passthrough = sms_filter_chain_send_datagram_passthrough,
.destroy = sms_filter_chain_send_datagram_destroy,
.free = sms_filter_chain_send_datagram_free
};
struct sms_filter_chain_send_datagram *send_msg =
g_new0(struct sms_filter_chain_send_datagram, 1);
sms_filter_message_init(&send_msg->message, chain, &send_datagram_fn);
sms_filter_convert_sms_address(&send_msg->addr, addr);
send_msg->send = send;
send_msg->destroy = destroy;
send_msg->data = data;
sms_datagram_set_bytes(send_msg, bytes, len);
send_msg->dst_port = dst_port;
send_msg->src_port = src_port;
send_msg->flags = flags;
return &send_msg->message;
}
/* sms_filter_chain_recv_text */
static inline struct sms_filter_chain_recv_text *
@@ -711,6 +858,30 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
}
}
void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
const struct sms_address *addr, int dstport,
int srcport, unsigned char *bytes, int len,
int flags, sms_send_datagram_cb_t sender,
ofono_destroy_func destroy, void *data)
{
if (chain) {
if (sms_filter_list) {
sms_filter_message_process
(sms_filter_send_datagram_new(chain, addr,
dstport, srcport, bytes, len,
flags, sender, data, destroy));
return;
}
if (sender) {
sender(chain->sms, addr, dstport, srcport, bytes, len,
flags, data);
}
}
if (destroy) {
destroy(data);
}
}
/* Does g_free(buf) when done */
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,
const struct ofono_uuid *uuid, int dst_port, int src_port,

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2015-2022 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
@@ -1043,6 +1043,64 @@ static void sms_send_message_submit(struct ofono_sms *sms,
message->pending = NULL;
}
static void sms_send_data_message_submit(struct ofono_sms *sms,
const struct sms_address *addr, int dstport,
int srcport, unsigned char *bytes, unsigned int len,
int flags, void *data)
{
struct sms_message_data *message = data;
const char *to = sms_address_to_string(addr);
GSList *msg_list = NULL;
gboolean use_16bit_ref = FALSE;
gboolean use_delivery_reports;
int err;
struct ofono_uuid uuid;
enum ofono_sms_submit_flag submit_flags;
enum sms_datagram_endianess endianess = SMS_DATAGRAM_ENDIANESS_GSM;
if (bytes == NULL) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_invalid_format(message->pending));
return;
}
if (flags & OFONO_SMS_DATA_FLAG_USE_LITTLE_ENDIAN)
endianess = SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN;
use_delivery_reports = flags & OFONO_SMS_DATA_FLAG_DELIVERY_REPORT;
msg_list = sms_datagram_prepare_with_endianess(to, bytes, len, sms->ref,
use_16bit_ref, srcport, dstport, TRUE,
use_delivery_reports, endianess);
if (msg_list == NULL) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_invalid_format(message->pending));
return;
}
submit_flags = OFONO_SMS_SUBMIT_FLAG_RETRY;
submit_flags |= OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS;
if (use_delivery_reports)
submit_flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;
err = __ofono_sms_txq_submit(sms, msg_list, submit_flags, &uuid,
message_queued, message->pending);
g_slist_free_full(msg_list, g_free);
if (err < 0) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_failed(message->pending));
return;
}
/* Ownership has been transfered to the message queue */
message->pending = NULL;
DBG("SMS data sent");
}
static void sms_send_message_destroy(void *data)
{
struct sms_message_data *message = data;
@@ -1099,6 +1157,49 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
static DBusMessage *sms_send_data_message(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_sms *sms = data;
const char *to;
unsigned char *bytes = NULL;
struct sms_message_data *message;
struct sms_address addr;
dbus_int32_t srcport;
dbus_int32_t dstport;
dbus_uint32_t flags;
int len;
if (!ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR,
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE, NULL))
return __ofono_error_access_denied(msg);
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
&bytes, &len,
DBUS_TYPE_INT32, &srcport,
DBUS_TYPE_INT32, &dstport,
DBUS_TYPE_UINT32, &flags,
DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg);
if (valid_phone_number_format(to) == FALSE)
return __ofono_error_invalid_format(msg);
message = g_new0(struct sms_message_data, 1);
message->pending = dbus_message_ref(msg);
sms_address_from_string(&addr, to);
__ofono_sms_filter_chain_send_datagram(sms->filter_chain, &addr,
dstport, srcport, bytes, len, flags,
sms_send_data_message_submit,
sms_send_message_destroy, message);
return NULL;
}
static DBusMessage *sms_get_messages(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -1216,6 +1317,15 @@ static const GDBusMethodTable sms_manager_methods[] = {
GDBUS_ARGS({ "to", "s" }, { "text", "s" }),
GDBUS_ARGS({ "path", "o" }),
sms_send_message) },
{ GDBUS_ASYNC_METHOD("SendDataMessage",
GDBUS_ARGS(
{ "to", "s" },
{ "data", "ay" },
{ "srcport", "i"},
{ "dstport", "i"},
{ "flags", "u"}),
GDBUS_ARGS({ "path", "o" }),
sms_send_data_message) },
{ GDBUS_METHOD("GetMessages",
NULL, GDBUS_ARGS({ "messages", "a(oa{sv})" }),
sms_get_messages) },

View File

@@ -3423,19 +3423,21 @@ static inline GSList *sms_list_append(GSList *l, const struct sms *in)
}
/*
* Prepares a datagram for transmission. Breaks up into fragments if
* necessary using ref as the concatenated message reference number.
* Prepares a datagram for transmission with requested endianess Breaks up
* into fragments if necessary using ref as the concatenated message reference
* number.
* Returns a list of sms messages in order.
*
* @use_delivery_reports: value for the Status-Report-Request field
* (23.040 3.2.9, 9.2.2.2)
*/
GSList *sms_datagram_prepare(const char *to,
GSList *sms_datagram_prepare_with_endianess(const char *to,
const unsigned char *data, unsigned int len,
guint16 ref, gboolean use_16bit_ref,
unsigned short src, unsigned short dst,
gboolean use_16bit_port,
gboolean use_delivery_reports)
gboolean use_delivery_reports,
enum sms_datagram_endianess endianess)
{
struct sms template;
unsigned int offset;
@@ -3462,10 +3464,22 @@ GSList *sms_datagram_prepare(const char *to,
template.submit.ud[0] += 6;
template.submit.ud[offset] = SMS_IEI_APPLICATION_ADDRESS_16BIT;
template.submit.ud[offset + 1] = 4;
template.submit.ud[offset + 2] = (dst & 0xff00) >> 8;
template.submit.ud[offset + 3] = dst & 0xff;
template.submit.ud[offset + 4] = (src & 0xff00) >> 8;
template.submit.ud[offset + 5] = src & 0xff;
switch (endianess) {
case SMS_DATAGRAM_ENDIANESS_GSM:
case SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN:
template.submit.ud[offset + 2] = (dst & 0xff00) >> 8;
template.submit.ud[offset + 3] = dst & 0xff;
template.submit.ud[offset + 4] = (src & 0xff00) >> 8;
template.submit.ud[offset + 5] = src & 0xff;
break;
case SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN:
template.submit.ud[offset + 2] = dst & 0xff;
template.submit.ud[offset + 3] = (dst & 0xff00) >> 8;
template.submit.ud[offset + 4] = src & 0xff;
template.submit.ud[offset + 5] = (src & 0xff00) >> 8;
break;
}
offset += 6;
} else {
@@ -3489,8 +3503,18 @@ GSList *sms_datagram_prepare(const char *to,
template.submit.ud[0] += 6;
template.submit.ud[offset] = SMS_IEI_CONCATENATED_16BIT;
template.submit.ud[offset + 1] = 4;
template.submit.ud[offset + 2] = (ref & 0xff00) >> 8;
template.submit.ud[offset + 3] = ref & 0xff;
switch (endianess) {
case SMS_DATAGRAM_ENDIANESS_GSM:
case SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN:
template.submit.ud[offset + 2] = (ref & 0xff00) >> 8;
template.submit.ud[offset + 3] = ref & 0xff;
break;
case SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN:
template.submit.ud[offset + 2] = ref & 0xff;
template.submit.ud[offset + 3] = (ref & 0xff00) >> 8;
break;
}
offset += 6;
} else {
@@ -3548,6 +3572,28 @@ GSList *sms_datagram_prepare(const char *to,
return r;
}
/*
* Prepares a datagram for transmission Breaks up into fragments if
* necessary using ref as the concatenated message reference number.
* Returns a list of sms messages in order.
*
* @use_delivery_reports: value for the Status-Report-Request field
* (23.040 3.2.9, 9.2.2.2)
*/
GSList *sms_datagram_prepare(const char *to,
const unsigned char *data, unsigned int len,
guint16 ref, gboolean use_16bit_ref,
unsigned short src, unsigned short dst,
gboolean use_16bit_port,
gboolean use_delivery_reports)
{
return sms_datagram_prepare_with_endianess(to, data, len, ref,
use_16bit_ref, src, dst,
use_16bit_port, use_delivery_reports,
SMS_DATAGRAM_ENDIANESS_GSM);
}
/*
* Prepares the text for transmission. Breaks up into fragments if
* necessary using ref as the concatenated message reference number.

View File

@@ -229,6 +229,12 @@ enum cbs_geo_scope {
CBS_GEO_SCOPE_CELL_NORMAL
};
enum sms_datagram_endianess {
SMS_DATAGRAM_ENDIANESS_GSM,
SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN,
SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN
};
struct sms_address {
enum sms_number_type number_type;
enum sms_numbering_plan numbering_plan;
@@ -574,6 +580,14 @@ GSList *sms_datagram_prepare(const char *to,
gboolean use_16bit_port,
gboolean use_delivery_reports);
GSList *sms_datagram_prepare_with_endianess(const char *to,
const unsigned char *data, unsigned int len,
guint16 ref, gboolean use_16bit_ref,
unsigned short src, unsigned short dst,
gboolean use_16bit_port,
gboolean use_delivery_reports,
enum sms_datagram_endianess endianess);
gboolean cbs_dcs_decode(guint8 dcs, gboolean *udhi, enum sms_class *cls,
enum sms_charset *charset, gboolean *compressed,
enum cbs_language *language, gboolean *iso639);

View File

@@ -1738,11 +1738,7 @@ static int voicecall_dial(struct ofono_voicecall *vc, const char *number,
string_to_phone_number(number, &ph);
/* No filtering for emergency calls */
if (is_emergency_number(vc, number))
vc->driver->dial(vc, &ph, clir, cb, vc);
else
dial_filter(vc, &ph, clir, cb, vc);
dial_filter(vc, &ph, clir, cb, vc);
return 0;
}
@@ -4262,14 +4258,10 @@ static void dial_request(struct ofono_voicecall *vc)
struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
__ofono_modem_inc_emergency_mode(modem);
/* No filtering for emergency calls */
vc->driver->dial(vc, &vc->dial_req->ph,
OFONO_CLIR_OPTION_DEFAULT, dial_request_cb, vc);
} else {
dial_filter(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
dial_request_cb, vc);
}
dial_filter(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
dial_request_cb, vc);
}
static void dial_req_disconnect_cb(const struct ofono_error *error, void *data)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2021 Jolla Ltd.
* Copyright (C) 2017-2022 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
@@ -41,6 +41,7 @@ struct ofono_watch_object {
guint imsi_watch_id;
guint spn_watch_id;
guint netreg_watch_id;
guint netreg_status_watch_id;
guint gprs_watch_id;
};
@@ -67,6 +68,7 @@ enum ofono_watch_signal {
SIGNAL_REG_MCC_CHANGED,
SIGNAL_REG_MNC_CHANGED,
SIGNAL_REG_NAME_CHANGED,
SIGNAL_REG_TECH_CHANGED,
SIGNAL_GPRS_CHANGED,
SIGNAL_GPRS_SETTINGS_CHANGED,
SIGNAL_COUNT
@@ -84,6 +86,7 @@ enum ofono_watch_signal {
#define SIGNAL_REG_MCC_CHANGED_NAME "ofono-watch-reg-mcc-changed"
#define SIGNAL_REG_MNC_CHANGED_NAME "ofono-watch-reg-mnc-changed"
#define SIGNAL_REG_NAME_CHANGED_NAME "ofono-watch-reg-name-changed"
#define SIGNAL_REG_TECH_CHANGED_NAME "ofono-watch-reg-tech-changed"
#define SIGNAL_GPRS_CHANGED_NAME "ofono-watch-gprs-changed"
#define SIGNAL_GPRS_SETTINGS_CHANGED_NAME "ofono-watch-gprs-settings-changed"
@@ -134,11 +137,13 @@ static void ofono_watch_emit_queued_signals(struct ofono_watch_object *self)
{
int i;
g_object_ref(self);
for (i = 0; self->queued_signals && i < SIGNAL_COUNT; i++) {
if (self->queued_signals & ofono_watch_signal_bit(i)) {
ofono_watch_signal_emit(self, i);
}
}
g_object_unref(self);
}
static void ofono_watch_iccid_update(struct ofono_watch_object *self,
@@ -349,6 +354,7 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
struct ofono_watch *watch = &self->pub;
struct ofono_netreg *netreg = watch->netreg;
enum ofono_netreg_status status = ofono_netreg_get_status(netreg);
enum ofono_access_technology act = ofono_netreg_get_technology(netreg);
const char *mcc = ofono_netreg_get_mcc(netreg);
const char *mnc = ofono_netreg_get_mnc(netreg);
const char *name = ofono_netreg_get_name(netreg);
@@ -357,6 +363,10 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
watch->reg_status = status;
ofono_watch_signal_queue(self, SIGNAL_REG_STATUS_CHANGED);
}
if (watch->reg_tech != act) {
watch->reg_tech = act;
ofono_watch_signal_queue(self, SIGNAL_REG_TECH_CHANGED);
}
if (g_strcmp0(self->reg_mcc, mcc)) {
g_free(self->reg_mcc);
watch->reg_mcc = self->reg_mcc = g_strdup(mcc);
@@ -374,17 +384,49 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
}
}
static void ofono_watch_netreg_status_notify(int status, int lac, int ci,
int tech, const char *mcc, const char *mnc, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_netreg_status_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->netreg_status_watch_id);
self->netreg_status_watch_id = 0;
}
static void ofono_watch_set_netreg(struct ofono_watch_object *self,
struct ofono_netreg *netreg)
{
struct ofono_watch *watch = &self->pub;
if (watch->netreg != netreg) {
if (self->netreg_status_watch_id) {
__ofono_netreg_remove_status_watch(watch->netreg,
self->netreg_status_watch_id);
/* The destroy callback clears it */
ASSERT(!self->netreg_status_watch_id);
}
watch->netreg = netreg;
ofono_watch_signal_queue(self, SIGNAL_NETREG_CHANGED);
if (netreg) {
self->netreg_status_watch_id =
__ofono_netreg_add_status_watch(netreg,
ofono_watch_netreg_status_notify, self,
ofono_watch_netreg_status_destroy);
}
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
}
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_netreg_notify(struct ofono_atom *atom,
@@ -417,6 +459,7 @@ static void ofono_watch_set_gprs(struct ofono_watch_object *self,
if (watch->gprs != gprs) {
watch->gprs = gprs;
ofono_watch_signal_queue(self, SIGNAL_GPRS_CHANGED);
ofono_watch_emit_queued_signals(self);
}
@@ -730,6 +773,7 @@ ADD_SIGNAL_HANDLER_PROC(reg_status,REG_STATUS)
ADD_SIGNAL_HANDLER_PROC(reg_mcc,REG_MCC)
ADD_SIGNAL_HANDLER_PROC(reg_mnc,REG_MNC)
ADD_SIGNAL_HANDLER_PROC(reg_name,REG_NAME)
ADD_SIGNAL_HANDLER_PROC(reg_tech,REG_TECH)
ADD_SIGNAL_HANDLER_PROC(gprs,GPRS)
static void ofono_watch_gprs_settings_signal_cb(struct ofono_watch_object *src,
@@ -775,21 +819,6 @@ void ofono_watch_remove_handlers(struct ofono_watch *watch, unsigned long *ids,
}
}
void __ofono_watch_netreg_changed(const char *path)
{
if (path && ofono_watch_table) {
struct ofono_watch_object *self =
g_hash_table_lookup(ofono_watch_table, path);
if (self) {
g_object_ref(self);
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
g_object_unref(self);
}
}
}
void __ofono_watch_gprs_settings_changed(const char *path,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings)
@@ -813,6 +842,7 @@ static void ofono_watch_object_init(struct ofono_watch_object *self)
struct ofono_watch *watch = &self->pub;
watch->reg_status = OFONO_NETREG_STATUS_NONE;
watch->reg_tech = OFONO_ACCESS_TECHNOLOGY_NONE;
}
static void ofono_watch_object_finalize(GObject *object)
@@ -847,6 +877,7 @@ static void ofono_watch_object_class_init(OfonoWatchObjectClass *klass)
NEW_SIGNAL(klass, REG_MCC);
NEW_SIGNAL(klass, REG_MNC);
NEW_SIGNAL(klass, REG_NAME);
NEW_SIGNAL(klass, REG_TECH);
NEW_SIGNAL(klass, GPRS);
ofono_watch_signals[SIGNAL_GPRS_SETTINGS_CHANGED] =
g_signal_new(SIGNAL_GPRS_SETTINGS_CHANGED_NAME,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
* Copyright (C) 2019-2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,7 +18,6 @@
#include <ofono/watch.h>
void __ofono_watch_netreg_changed(const char *path);
void __ofono_watch_gprs_settings_changed(const char *path,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019-2021 Jolla Ltd.
* Copyright (C) 2019-2022 Jolla Ltd.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -122,6 +122,9 @@ static const struct test_method_name_data method_name_tests[] = {
},{
OFONO_DBUS_ACCESS_INTF_OEMRAW,
OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_IMS,
OFONO_DBUS_ACCESS_IMS_METHOD_COUNT
}
};

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2022 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
@@ -57,17 +57,25 @@ struct ofono_gprs {
struct ofono_netreg {
struct ofono_atom atom;
struct ofono_watchlist *status_watches;
enum ofono_netreg_status status;
enum ofono_access_technology tech;
const char *mcc;
const char *mnc;
const char *name;
};
int ofono_netreg_get_status(struct ofono_netreg *netreg)
enum ofono_netreg_status ofono_netreg_get_status(struct ofono_netreg *netreg)
{
return netreg ? netreg->status : OFONO_NETREG_STATUS_NONE;
}
enum ofono_access_technology
ofono_netreg_get_technology (struct ofono_netreg *netreg)
{
return netreg ? netreg->tech : OFONO_ACCESS_TECHNOLOGY_NONE;
}
const char *ofono_netreg_get_mcc(struct ofono_netreg *netreg)
{
return netreg ? netreg->mcc : NULL;
@@ -83,6 +91,44 @@ const char *ofono_netreg_get_name(struct ofono_netreg *netreg)
return netreg ? netreg->name : NULL;
}
static void netreg_notify(struct ofono_netreg *netreg)
{
GSList *l;
for (l = netreg->status_watches->items; l; l = l->next) {
struct ofono_watchlist_item *item = l->data;
ofono_netreg_status_notify_cb_t notify = item->notify;
notify(netreg->status, -1, -1, netreg->tech, netreg->mcc,
netreg->mnc, item->notify_data);
}
}
static unsigned int add_watch_item(struct ofono_watchlist *list,
void *notify, void *data, ofono_destroy_func destroy)
{
struct ofono_watchlist_item *watch =
g_new0(struct ofono_watchlist_item, 1);
watch->notify = notify;
watch->destroy = destroy;
watch->notify_data = data;
return __ofono_watchlist_add_item(list, watch);
}
unsigned int __ofono_netreg_add_status_watch(struct ofono_netreg *netreg,
ofono_netreg_status_notify_cb_t notify,
void *data, ofono_destroy_func destroy)
{
return add_watch_item(netreg->status_watches, notify, data, destroy);
}
gboolean __ofono_netreg_remove_status_watch(struct ofono_netreg *netreg,
unsigned int id)
{
return __ofono_watchlist_remove_item(netreg->status_watches, id);
}
/* Fake ofono_sim */
struct ofono_sim {
@@ -98,18 +144,6 @@ struct ofono_sim {
struct ofono_watchlist *state_watches;
};
static unsigned int add_watch_item(struct ofono_watchlist *list,
void *notify, void *data, ofono_destroy_func destroy)
{
struct ofono_watchlist_item *watch =
g_new0(struct ofono_watchlist_item, 1);
watch->notify = notify;
watch->destroy = destroy;
watch->notify_data = data;
return __ofono_watchlist_add_item(list, watch);
}
unsigned int ofono_sim_add_iccid_watch(struct ofono_sim *sim,
ofono_sim_iccid_event_cb_t cb, void *data,
ofono_destroy_func destroy)
@@ -342,7 +376,7 @@ unsigned int __ofono_modem_add_atom_watch(struct ofono_modem *modem,
return id;
}
static void call_watches(struct ofono_atom *atom,
static void atom_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond)
{
GSList *l;
@@ -400,7 +434,7 @@ static void test_modem_register_atom(struct ofono_modem *modem,
if (!atom->registered) {
atom->registered = TRUE;
modem->atoms = g_slist_append(modem->atoms, atom);
call_watches(atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED);
atom_notify(atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED);
}
}
@@ -409,7 +443,7 @@ static void test_modem_unregister_atom(struct ofono_modem *modem,
{
if (atom->registered) {
atom->registered = FALSE;
call_watches(atom, OFONO_ATOM_WATCH_CONDITION_UNREGISTERED);
atom_notify(atom, OFONO_ATOM_WATCH_CONDITION_UNREGISTERED);
modem->atoms = g_slist_remove(modem->atoms, atom);
}
}
@@ -428,6 +462,9 @@ static void test_modem_init1(struct ofono_modem *modem, const char *path)
netreg->atom.type = OFONO_ATOM_TYPE_NETREG;
netreg->atom.modem = modem;
netreg->atom.data = netreg;
netreg->status = OFONO_NETREG_STATUS_NOT_REGISTERED;
netreg->tech = OFONO_ACCESS_TECHNOLOGY_NONE;
netreg->status_watches = __ofono_watchlist_new(g_free);
gprs->atom.type = OFONO_ATOM_TYPE_GPRS;
gprs->atom.modem = modem;
@@ -455,15 +492,17 @@ static void test_modem_init(struct ofono_modem *modem)
static void test_modem_shutdown(struct ofono_modem *modem)
{
struct ofono_sim *sim = &modem->sim;
struct ofono_netreg *netreg = &modem->netreg;
call_modemwatches(modem, FALSE);
g_modem_list = g_slist_remove(g_modem_list, modem);
g_slist_free(modem->atoms);
__ofono_watchlist_free(sim->iccid_watches);
__ofono_watchlist_free(sim->imsi_watches);
__ofono_watchlist_free(sim->state_watches);
__ofono_watchlist_free(sim->spn_watches);
__ofono_watchlist_free(netreg->status_watches);
__ofono_watchlist_free(modem->atom_watches);
__ofono_watchlist_free(modem->online_watches);
}
@@ -504,8 +543,6 @@ static void test_basic(void)
NULL, NULL));
ofono_watch_remove_handler(NULL, 0);
ofono_watch_remove_handlers(NULL, NULL, 0);
__ofono_watch_netreg_changed(NULL);
__ofono_watch_netreg_changed(TEST_PATH);
__ofono_watch_gprs_settings_changed
(NULL, OFONO_GPRS_CONTEXT_TYPE_ANY, NULL);
__ofono_watch_gprs_settings_changed
@@ -623,7 +660,7 @@ static void test_netreg(void)
struct ofono_watch *watch;
struct ofono_modem modem;
struct ofono_netreg *netreg = &modem.netreg;
gulong id[5];
gulong id[6];
int n[G_N_ELEMENTS(id)];
#define NETREG 0
@@ -631,8 +668,7 @@ static void test_netreg(void)
#define REG_MCC 2
#define REG_MNC 3
#define REG_NAME 4
__ofono_watch_netreg_changed(TEST_PATH); /* No effect (yet) */
#define REG_TECH 5
memset(&modem, 0, sizeof(modem));
__ofono_modemwatch_init();
@@ -652,16 +688,20 @@ static void test_netreg(void)
(watch, test_inc_cb, n + REG_MNC);
id[REG_NAME] = ofono_watch_add_reg_name_changed_handler
(watch, test_inc_cb, n + REG_NAME);
id[REG_TECH] = ofono_watch_add_reg_tech_changed_handler
(watch, test_inc_cb, n + REG_TECH);
test_modem_register_atom(&modem, &netreg->atom);
g_assert(watch->netreg == netreg);
g_assert(watch->reg_status == netreg->status);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert_cmpint(watch->reg_status, == ,netreg->status);
g_assert_cmpint(watch->reg_tech, == ,netreg->tech);
g_assert_cmpint(n[NETREG], == ,1);
g_assert_cmpint(n[REG_STATUS], == ,1);
g_assert_cmpint(n[REG_TECH], == ,0);
n[NETREG] = 0;
n[REG_STATUS] = 0;
netreg->status++;
__ofono_watch_netreg_changed(TEST_PATH);
netreg_notify(netreg);
g_assert(watch->reg_status == netreg->status);
g_assert(n[REG_STATUS] == 1);
n[REG_STATUS] = 0;
@@ -669,31 +709,35 @@ static void test_netreg(void)
netreg->mcc = TEST_MCC;
netreg->mnc = TEST_MNC;
netreg->name = TEST_NAME;
__ofono_watch_netreg_changed(TEST_PATH);
__ofono_watch_netreg_changed(TEST_PATH); /* This one has no effect */
__ofono_watch_netreg_changed(TEST_PATH_1); /* This one too */
g_assert(!n[REG_STATUS]);
g_assert(n[REG_MCC] == 1);
g_assert(n[REG_MNC] == 1);
g_assert(n[REG_NAME] == 1);
g_assert(!g_strcmp0(watch->reg_mcc, netreg->mcc));
g_assert(!g_strcmp0(watch->reg_mnc, netreg->mnc));
g_assert(!g_strcmp0(watch->reg_name, netreg->name));
netreg->tech = OFONO_ACCESS_TECHNOLOGY_EUTRAN;
netreg_notify(netreg);
netreg_notify(netreg); /* This one has no effect */
g_assert_cmpint(n[REG_STATUS], == ,0);
g_assert_cmpint(n[REG_MCC], == ,1);
g_assert_cmpint(n[REG_MNC], == ,1);
g_assert_cmpint(n[REG_NAME], == ,1);
g_assert_cmpint(n[REG_TECH], == ,1);
g_assert_cmpstr(watch->reg_mcc, == ,netreg->mcc);
g_assert_cmpstr(watch->reg_mnc, == ,netreg->mnc);
g_assert_cmpstr(watch->reg_name, == ,netreg->name);
n[REG_MCC] = 0;
n[REG_MNC] = 0;
n[REG_NAME] = 0;
n[REG_TECH] = 0;
test_modem_unregister_atom(&modem, &netreg->atom);
g_assert(!watch->netreg);
g_assert(watch->reg_status == OFONO_NETREG_STATUS_NONE);
g_assert_cmpint(watch->reg_status, == ,OFONO_NETREG_STATUS_NONE);
g_assert_cmpint(watch->reg_tech, == ,OFONO_ACCESS_TECHNOLOGY_NONE);
g_assert(!watch->reg_mcc);
g_assert(!watch->reg_mnc);
g_assert(!watch->reg_name);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert(n[REG_MCC] == 1);
g_assert(n[REG_MNC] == 1);
g_assert(n[REG_NAME] == 1);
g_assert_cmpint(n[NETREG], == ,1);
g_assert_cmpint(n[REG_STATUS], == ,1);
g_assert_cmpint(n[REG_MCC], == ,1);
g_assert_cmpint(n[REG_MNC], == ,1);
g_assert_cmpint(n[REG_NAME], == ,1);
g_assert_cmpint(n[REG_TECH], == ,1);
memset(n, 0, sizeof(n));
netreg->mcc = NULL;
@@ -702,20 +746,24 @@ static void test_netreg(void)
test_modem_register_atom(&modem, &netreg->atom);
g_assert(watch->netreg == netreg);
g_assert(watch->reg_status == netreg->status);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert_cmpint(watch->reg_status, == ,netreg->status);
g_assert_cmpint(watch->reg_tech, == ,netreg->tech);
g_assert_cmpint(n[NETREG], == ,1);
g_assert_cmpint(n[REG_STATUS], == ,1);
n[NETREG] = 0;
n[REG_STATUS] = 0;
n[REG_TECH] = 0;
test_modem_shutdown(&modem);
g_assert(!watch->netreg);
g_assert(watch->reg_status == OFONO_NETREG_STATUS_NONE);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert(!n[REG_MCC]);
g_assert(!n[REG_MNC]);
g_assert(!n[REG_NAME]);
g_assert_cmpint(watch->reg_status, == ,OFONO_NETREG_STATUS_NONE);
g_assert_cmpint(watch->reg_tech, == ,OFONO_ACCESS_TECHNOLOGY_NONE);
g_assert_cmpint(n[NETREG], == ,1);
g_assert_cmpint(n[REG_STATUS], == ,1);
g_assert_cmpint(n[REG_TECH], == ,1);
g_assert_cmpint(n[REG_MCC], == ,0);
g_assert_cmpint(n[REG_MNC], == ,0);
g_assert_cmpint(n[REG_NAME], == ,0);
ofono_watch_remove_all_handlers(watch, id);
ofono_watch_unref(watch);