mirror of
https://github.com/sailfishos/ofono
synced 2025-11-30 14:41:04 +08:00
Compare commits
12 Commits
1.29+git9
...
upgrade-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44f5f8f474 | ||
|
|
fe1e9ce9c9 | ||
|
|
e4fc0626c1 | ||
|
|
08ce5308cf | ||
|
|
b680de231d | ||
|
|
fe85fbbd70 | ||
|
|
c52151b8c9 | ||
|
|
88378c4c77 | ||
|
|
8a9c0ab853 | ||
|
|
a994a95186 | ||
|
|
aec8bdd69d | ||
|
|
bdf046094f |
@@ -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".
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
472
ofono/src/ims.c
472
ofono/src/ims.c
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
112
ofono/src/sms.c
112
ofono/src/sms.c
@@ -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) },
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user