Compare commits

...

34 Commits

Author SHA1 Message Date
Matti Lehtimäki
d0b3523f13 Merge pull request #46 from sailfishos/jb63008
Backport several security fixes from upstream
2024-12-29 16:53:46 +02:00
Sicelo A. Mhlongo
b0720e92ed ussd: ensure ussd content fits in buffers
Fixes: CVE-2024-7539
2024-12-23 13:55:48 +02:00
Sicelo A. Mhlongo
822abb5965 atmodem: sms: ensure buffer is initialized before use
Fixes: CVE-2024-7540
Fixes: CVE-2024-7541
Fixes: CVE-2024-7542
2024-12-23 13:55:48 +02:00
Sicelo A. Mhlongo
3df702e03b smsutil: check status report fits in buffer
Fixes CVE-2023-4232
2024-12-23 13:55:43 +02:00
Sicelo A. Mhlongo
7649838ec1 smsutil: check deliver reports fit in buffer
Fixes CVE-2023-4235
2024-12-23 13:55:43 +02:00
Sicelo A. Mhlongo
0a2cc76b72 stkutil: ensure data fits in buffer
Fixes CVE-2024-7545
2024-12-23 13:55:43 +02:00
Ivaylo Dimitrov
f65bb725d0 Fix CVE-2024-7546 2024-12-23 13:55:40 +02:00
Ivaylo Dimitrov
02dded4a84 Fix CVE-2024-7547 2024-12-23 13:55:40 +02:00
Ivaylo Dimitrov
4f51a41cc0 stkutil: Fix CVE-2024-7543 2024-12-23 13:55:40 +02:00
Ivaylo Dimitrov
463b263318 stkutil: Fix CVE-2024-7544 2024-12-23 13:55:40 +02:00
Jean-Marie Lemetayer
d40b258776 smsutil: check that user data length fits in internal buffer
This addresses CVE-2023-2794.
2024-12-23 13:55:36 +02:00
Pekka Vuorela
32ab6b3c78 Merge pull request #44 from sailfishos/broadband_info_dependency
[ofono] Require (again) mobile-broadband-provider-info. JB#57703
2024-02-20 14:25:05 +02:00
Pekka Vuorela
13c8d6cf97 [ofono] Require (again) mobile-broadband-provider-info. JB#57703
Commit 33744c51 made it recommended only, but the reason for change
seemed more of not failing building images without anything providing
the ofono-configs. On provider-info there shouldn't be similar
problems and there should be a dependency for it.
2024-02-20 13:15:00 +02:00
Pekka Vuorela
a7227c6cad Merge pull request #43 from sailfishos/conf_unit_test
[ofono] Don't care about whitespace in config unit test. JB#61330
2024-02-19 16:01:47 +02:00
Pekka Vuorela
cff7c7adb1 [ofono] Don't care about whitespace in config unit test. JB#61330
New glib keeps some extra line feed on the merged conf file data.
It shouldn't really matter so ignore such differences on the test.
2024-02-19 15:56:39 +02:00
Matti Lehtimäki
a50522b062 Merge pull request #42 from sailfishos/jb61571
Backport two patches from upstream to fix CVE-2023-4233 and CVE-2023-4234
2024-02-19 14:13:18 +02:00
Denis Grigorev
bb7d65f41a smsutil: Validate the length of the address field
This addresses CVE-2023-4233.
2024-02-16 17:50:58 +02:00
Denis Grigorev
278f28d15c smsutil: Check that submit report fits in memory
This addresses CVE-2023-4234.
2024-02-16 17:50:43 +02:00
Matti Lehtimäki
3afa0876c6 Merge pull request #40 from sailfishos/jb58763
[ofono] Add support for NR networks. JB#58763
2023-04-14 22:36:31 +03:00
Matti Lehtimäki
04162f719e [ofono] Add support for NR networks. JB#58763 2023-01-02 11:26:51 +02:00
Slava Monich
4ae4d688ce Merge pull request #41 from monich/uaf
Fix use after free
2023-01-02 11:13:43 +02:00
Slava Monich
224b551feb [voicecall] Fix use after free. JB#54354
Thanks to Denis Grigorev for pointing it out.
2023-01-02 00:38:40 +02:00
Slava Monich
6acf808d89 Merge pull request #38 from monich/conf-mask
Allow merging mask conf values
2022-11-07 16:37:19 +02:00
Slava Monich
942b2efc3b [ofono] Allow merging mask conf values. JB#59210
To allow syntax like disableFeatures += voice
2022-11-07 16:17:36 +02:00
Slava Monich
301b880a87 Merge pull request #37 from monich/cbs-topics-max
Widen the range of allowed cell broadcast channels
2022-10-27 02:12:01 +03:00
Slava Monich
933525829f [cbs] Widen the range of allowed cell broadcast channels. JB#5761 2022-10-25 13:39:33 +03:00
Slava Monich
d8df18c80c Updated upstream hash to point to 1.29 2022-10-25 13:25:52 +03:00
Slava Monich
47fd559c1b Merge pull request #36 from monich/jb58727
Remove event source after closing BT socket
2022-09-08 01:18:26 +03:00
Slava Monich
8fa9a7068f [hfp_ag_bluez5] Remove event source after closing BT socket. JB#58727
Otherwise GIOChannel stays alive and glib main loop keeps polling
invalid fd and eating up CPU time.
2022-09-07 17:21:24 +03:00
Slava Monich
10c1d7ac75 [ims] Tweak the treatment of the default Registration value
To handle the case if it's not IMS_REG_AUTO
2022-05-09 17:57:41 +03:00
Slava Monich
81ad45dfd9 Merge pull request #33 from monich/ims
org.ofono.IpMultimediaSystem D-Bus API tweaks
2022-04-21 04:33:24 +03:00
Slava Monich
0e27cf811b [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-04-21 03:40:28 +03:00
Slava Monich
5ec5081b7d [watch] Added reg_tech watch. JB#57999 2022-04-20 20:23:02 +03:00
Slava Monich
d2cae30a03 [ims] D-Bus access control for org.ofono.IpMultimediaSystem. JB#57408 2022-04-14 01:28:01 +03:00
35 changed files with 929 additions and 169 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

@@ -407,7 +407,7 @@ static void at_cmt_notify(GAtResult *result, gpointer user_data)
struct sms_data *data = ofono_sms_get_data(sms);
GAtResultIter iter;
const char *hexpdu;
unsigned char pdu[176];
unsigned char pdu[176] = {0};
long pdu_len;
int tpdu_len;
@@ -473,7 +473,7 @@ static void at_cmgr_notify(GAtResult *result, gpointer user_data)
struct sms_data *data = ofono_sms_get_data(sms);
GAtResultIter iter;
const char *hexpdu;
unsigned char pdu[176];
unsigned char pdu[176] = {0};
long pdu_len;
int tpdu_len;
@@ -655,7 +655,7 @@ static void at_cmgl_notify(GAtResult *result, gpointer user_data)
struct sms_data *data = ofono_sms_get_data(sms);
GAtResultIter iter;
const char *hexpdu;
unsigned char pdu[176];
unsigned char pdu[176] = {0};
long pdu_len;
int tpdu_len;
int index;

View File

@@ -105,7 +105,7 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
const char *content;
int dcs;
enum sms_charset charset;
unsigned char msg[160];
unsigned char msg[160] = {0};
const unsigned char *msg_ptr = NULL;
long msg_len;
@@ -123,6 +123,9 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
if (!g_at_result_iter_next_number(&iter, &dcs))
dcs = 0;
if (strlen(content) > sizeof(msg) * 2)
goto out;
if (!cbs_dcs_decode(dcs, NULL, NULL, &charset, NULL, NULL, NULL)) {
ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
status = 4; /* Not supported */

View File

@@ -50,7 +50,7 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
GAtResultIter iter;
int status, dcs;
const char *content;
unsigned char msg[160];
unsigned char msg[160] = {0};
const unsigned char *msg_ptr = NULL;
long msg_len;
@@ -68,6 +68,9 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
if (!g_at_result_iter_next_number(&iter, &dcs))
dcs = 0;
if (strlen(content) > sizeof(msg) * 2)
goto out;
msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
out:

View File

@@ -49,7 +49,7 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
GAtResultIter iter;
int status, dcs;
const char *content;
unsigned char msg[160];
unsigned char msg[160] = {0};
const unsigned char *msg_ptr = NULL;
long msg_len;
@@ -67,6 +67,9 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
if (!g_at_result_iter_next_number(&iter, &dcs))
dcs = 0;
if (strlen(content) > sizeof(msg) * 2)
goto out;
msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
out:

View File

@@ -23,14 +23,17 @@ extern "C" {
#endif
#include <ofono/types.h>
#include <stdint.h>
enum ofono_cell_type {
OFONO_CELL_TYPE_GSM,
OFONO_CELL_TYPE_WCDMA,
OFONO_CELL_TYPE_LTE
OFONO_CELL_TYPE_LTE,
OFONO_CELL_TYPE_NR /* Since 1.29+git8 */
};
#define OFONO_CELL_INVALID_VALUE (INT_MAX)
#define OFONO_CELL_INVALID_VALUE_INT64 (INT64_MAX)
struct ofono_cell_info_gsm {
int mcc; /* Mobile Country Code (0..999) */
@@ -70,6 +73,22 @@ struct ofono_cell_info_lte {
int timingAdvance; /* (Distance = 300m/us) TS 36.321 */
};
/* Since 1.29+git8 */
struct ofono_cell_info_nr {
int mcc; /* Mobile Country Code (0..999) */
int mnc; /* Mobile Network Code (0..999) */
int64_t nci; /* NR Cell Identity */
int pci; /* Physical cell id (0..1007) */
int tac; /* Tracking area code */
int nrarfcn; /* 22-bit NR Absolute RC Channel Number */
int ssRsrp; /* SS Reference Signal Receive Power TS 38.215 */
int ssRsrq; /* SS Reference Signal Receive Quality TS 38.215 and 38.133 */
int ssSinr; /* SS Reference Signal-to-Noise Ratio TS 38.215 and 38.133*/
int csiRsrp; /* CSI Reference Signal Receive Power TS 38.215 */
int csiRsrq; /* CSI Reference Signal Receive Quality TS 38.215 */
int csiSinr; /* CSI Reference Signal-to-Noise Ratio TS 38.215 and 38.133 */
};
typedef struct ofono_cell {
enum ofono_cell_type type;
ofono_bool_t registered;
@@ -77,6 +96,7 @@ typedef struct ofono_cell {
struct ofono_cell_info_gsm gsm;
struct ofono_cell_info_wcdma wcdma;
struct ofono_cell_info_lte lte;
struct ofono_cell_info_nr nr; /* Since 1.29+git8 */
} info;
} *ofono_cell_ptr;

View File

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

@@ -34,6 +34,7 @@ enum ofono_radio_access_mode {
OFONO_RADIO_ACCESS_MODE_GSM = 0x1,
OFONO_RADIO_ACCESS_MODE_UMTS = 0x2,
OFONO_RADIO_ACCESS_MODE_LTE = 0x4,
OFONO_RADIO_ACCESS_MODE_NR = 0x8, /* Since 1.29+git8 */
};
enum ofono_radio_band_gsm {

View File

@@ -57,7 +57,11 @@ enum ofono_access_technology {
OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA = 6,
OFONO_ACCESS_TECHNOLOGY_EUTRAN = 7,
OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 = 8,
OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 = 9
OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 = 9,
OFONO_ACCESS_TECHNOLOGY_EUTRA_5GCN = 10, /* Since 1.29+git8 */
OFONO_ACCESS_TECHNOLOGY_NR_5GCN = 11, /* Since 1.29+git8 */
OFONO_ACCESS_TECHNOLOGY_NG_RAN = 12, /* Since 1.29+git8 */
OFONO_ACCESS_TECHNOLOGY_EUTRA_NR = 13, /* Since 1.29+git8 */
};
/* 27.007 Section 6.2 */

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

@@ -2,6 +2,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2011 Intel Corporation. All rights reserved.
* Copyright (C) 2018-2022 Jolla Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -52,6 +53,11 @@ typedef struct GAtResult GAtResult;
#define HFP_AG_DRIVER "hfp-ag-driver"
struct watch_fd {
guint id;
int fd;
};
static gboolean hfp_ag_enabled;
static guint service_watch_id;
static guint modemwatch_id;
@@ -145,11 +151,12 @@ static struct ofono_handsfree_card_driver hfp_ag_driver = {
static void connection_destroy(gpointer data)
{
int fd = GPOINTER_TO_INT(data);
struct watch_fd *watch = data;
DBG("fd %d", fd);
DBG("fd %d", watch->fd);
close(fd);
g_source_remove(watch->id);
g_free(watch);
}
static gboolean io_hup_cb(GIOChannel *io, GIOCondition cond, gpointer data)
@@ -169,7 +176,8 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
DBusMessageIter entry;
const char *device;
GIOChannel *io;
int fd, fd_dup;
int fd;
struct watch_fd *watch;
struct sockaddr_rc saddr;
socklen_t optlen;
struct ofono_emulator *em;
@@ -252,10 +260,12 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
emulator = em;
ofono_emulator_register(em, fd);
fd_dup = dup(fd);
io = g_io_channel_unix_new(fd_dup);
g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_HUP, io_hup_cb,
g_strdup(device), g_free);
watch = g_new(struct watch_fd, 1);
watch->fd = dup(fd);
io = g_io_channel_unix_new(watch->fd);
g_io_channel_set_close_on_unref(io, TRUE);
watch->id = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_HUP,
io_hup_cb, g_strdup(device), g_free);
g_io_channel_unref(io);
card = ofono_handsfree_card_create(0,
@@ -269,8 +279,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
ofono_emulator_set_handsfree_card(em, card);
g_hash_table_insert(connection_hash, g_strdup(device),
GINT_TO_POINTER(fd_dup));
g_hash_table_insert(connection_hash, g_strdup(device), watch);
return dbus_message_new_method_return(msg);
@@ -304,7 +313,7 @@ static DBusMessage *profile_disconnection(DBusConnection *conn,
{
DBusMessageIter iter;
const char *device;
gpointer fd;
struct watch_fd *watch;
DBG("Profile handler RequestDisconnection");
@@ -318,11 +327,11 @@ static DBusMessage *profile_disconnection(DBusConnection *conn,
DBG("%s", device);
fd = g_hash_table_lookup(connection_hash, device);
if (fd == NULL)
watch = g_hash_table_lookup(connection_hash, device);
if (watch == NULL)
goto invalid;
shutdown(GPOINTER_TO_INT(fd), SHUT_RDWR);
shutdown(watch->fd, SHUT_RDWR);
g_hash_table_remove(connection_hash, device);

View File

@@ -771,7 +771,7 @@ static void sim_cbmi_read_cb(int ok, int length, int record,
mi = (data[i] << 8) + data[i+1];
if (mi > 999)
if (mi > CBS_MAX_TOPIC)
continue;
range = g_new0(struct cbs_topic_range, 1);
@@ -818,7 +818,7 @@ static void sim_cbmir_read_cb(int ok, int length, int record,
min = (data[i] << 8) + data[i+1];
max = (data[i+2] << 8) + data[i+3];
if (min > 999 || max > 999 || min > max)
if (min > CBS_MAX_TOPIC || max > CBS_MAX_TOPIC || min > max)
continue;
range = g_new0(struct cbs_topic_range, 1);

View File

@@ -57,14 +57,19 @@ struct cell_property {
const char *name;
glong off;
int flag;
int type;
};
#define CELL_GSM_PROPERTY(value,name) \
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_gsm,name), value }
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_gsm,name), value, DBUS_TYPE_INT32 }
#define CELL_WCDMA_PROPERTY(value,name) \
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_wcdma,name), value }
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_wcdma,name), value, DBUS_TYPE_INT32 }
#define CELL_LTE_PROPERTY(value,name) \
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_lte,name), value }
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_lte,name), value, DBUS_TYPE_INT32 }
#define CELL_NR_PROPERTY(value,name) \
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_nr,name), value, DBUS_TYPE_INT32 }
#define CELL_NR_PROPERTY64(value,name) \
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_nr,name), value, DBUS_TYPE_INT64 }
static const struct cell_property cell_gsm_properties [] = {
CELL_GSM_PROPERTY(0x001,mcc),
@@ -104,6 +109,21 @@ static const struct cell_property cell_lte_properties [] = {
CELL_LTE_PROPERTY(0x800,timingAdvance)
};
static const struct cell_property cell_nr_properties [] = {
CELL_NR_PROPERTY(0x001,mcc),
CELL_NR_PROPERTY(0x002,mnc),
CELL_NR_PROPERTY64(0x004,nci),
CELL_NR_PROPERTY(0x008,pci),
CELL_NR_PROPERTY(0x010,tac),
CELL_NR_PROPERTY(0x020,nrarfcn),
CELL_NR_PROPERTY(0x040,ssRsrp),
CELL_NR_PROPERTY(0x080,ssRsrq),
CELL_NR_PROPERTY(0x100,ssSinr),
CELL_NR_PROPERTY(0x200,csiRsrp),
CELL_NR_PROPERTY(0x400,csiRsrq),
CELL_NR_PROPERTY(0x800,csiSinr),
};
#define CELL_PROPERTY_REGISTERED 0x1000
typedef void (*cell_info_dbus_append_fn)(DBusMessageIter *it,
@@ -124,6 +144,8 @@ static const char *cell_info_dbus_cell_type_str(enum ofono_cell_type type)
return "wcdma";
case OFONO_CELL_TYPE_LTE:
return "lte";
case OFONO_CELL_TYPE_NR:
return "nr";
default:
return "unknown";
}
@@ -142,6 +164,9 @@ static const struct cell_property *cell_info_dbus_cell_properties
case OFONO_CELL_TYPE_LTE:
*count = G_N_ELEMENTS(cell_lte_properties);
return cell_lte_properties;
case OFONO_CELL_TYPE_NR:
*count = G_N_ELEMENTS(cell_nr_properties);
return cell_nr_properties;
default:
*count = 0;
return NULL;
@@ -202,10 +227,18 @@ static void cell_info_dbus_append_properties(DBusMessageIter *it,
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, "{sv}", &dict);
for (i = 0; i < n; i++) {
gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
if (value != OFONO_CELL_INVALID_VALUE) {
ofono_dbus_dict_append(&dict, prop[i].name,
DBUS_TYPE_INT32, &value);
if (prop[i].type == DBUS_TYPE_INT64) {
gint64 value = G_STRUCT_MEMBER(gint64, &cell->info, prop[i].off);
if (value != OFONO_CELL_INVALID_VALUE_INT64) {
ofono_dbus_dict_append(&dict, prop[i].name,
DBUS_TYPE_INT64, &value);
}
} else {
gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
if (value != OFONO_CELL_INVALID_VALUE) {
ofono_dbus_dict_append(&dict, prop[i].name,
DBUS_TYPE_INT32, &value);
}
}
}
dbus_message_iter_close_container(it, &dict);
@@ -375,11 +408,20 @@ static int cell_info_dbus_compare(const struct ofono_cell *c1,
for (i = 0; i < n; i++) {
const glong offset = prop[i].off;
gint32 v1 = G_STRUCT_MEMBER(int, &c1->info, offset);
gint32 v2 = G_STRUCT_MEMBER(int, &c2->info, offset);
if (prop[i].type == DBUS_TYPE_INT64) {
gint64 v1 = G_STRUCT_MEMBER(gint64, &c1->info, offset);
gint64 v2 = G_STRUCT_MEMBER(gint64, &c2->info, offset);
if (v1 != v2) {
mask |= prop[i].flag;
if (v1 != v2) {
mask |= prop[i].flag;
}
} else {
gint32 v1 = G_STRUCT_MEMBER(int, &c1->info, offset);
gint32 v2 = G_STRUCT_MEMBER(int, &c2->info, offset);
if (v1 != v2) {
mask |= prop[i].flag;
}
}
}
@@ -427,7 +469,7 @@ static void cell_info_dbus_property_changed(CellInfoDBus *dbus,
ofono_dbus_clients_signal_property_changed(
dbus->clients, entry->path,
CELL_DBUS_INTERFACE, prop[i].name,
DBUS_TYPE_INT32,
prop[i].type,
G_STRUCT_MEMBER_P(&cell->info, prop[i].off));
mask &= ~prop[i].flag;
}

View File

@@ -70,6 +70,23 @@ int ofono_cell_compare_location(const struct ofono_cell *c1,
} else {
return l1->tac - l2->tac;
}
} else if (c1->type == OFONO_CELL_TYPE_NR) {
const struct ofono_cell_info_nr *n1 =
&c1->info.nr;
const struct ofono_cell_info_nr *n2 =
&c2->info.nr;
if (n1->mcc != n2->mcc) {
return n1->mcc - n2->mcc;
} else if (n1->mnc != n2->mnc) {
return n1->mnc - n2->mnc;
} else if (n1->nci != n2->nci) {
return n1->nci - n2->nci;
} else if (n1->pci != n2->pci) {
return n1->pci - n2->pci;
} else {
return n1->tac - n2->tac;
}
} else {
ofono_warn("Unexpected cell type");
return 0;

View File

@@ -710,6 +710,12 @@ const char *registration_tech_to_string(enum ofono_access_technology tech)
return "lte-cat-m1";
case ACCESS_TECHNOLOGY_NB_IOT_NB1:
return "lte-cat-nb1";
case ACCESS_TECHNOLOGY_EUTRA_5GCN:
return "lte";
case ACCESS_TECHNOLOGY_NR_5GCN:
case ACCESS_TECHNOLOGY_NG_RAN:
case ACCESS_TECHNOLOGY_EUTRA_NR:
return "nr";
case OFONO_ACCESS_TECHNOLOGY_NONE:
break;
default:

View File

@@ -46,6 +46,14 @@
OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 /* 8 */
#define ACCESS_TECHNOLOGY_NB_IOT_NB1 \
OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 /* 9 */
#define ACCESS_TECHNOLOGY_EUTRA_5GCN \
OFONO_ACCESS_TECHNOLOGY_EUTRA_5GCN /* 10 */
#define ACCESS_TECHNOLOGY_NR_5GCN \
OFONO_ACCESS_TECHNOLOGY_NR_5GCN /* 11 */
#define ACCESS_TECHNOLOGY_NG_RAN \
OFONO_ACCESS_TECHNOLOGY_NG_RAN /* 12 */
#define ACCESS_TECHNOLOGY_EUTRA_NR \
OFONO_ACCESS_TECHNOLOGY_EUTRA_NR /* 13 */
/* 27.007 Section 7.2 <stat> */
#define NETWORK_REGISTRATION_STATUS_NOT_REGISTERED \

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2015-2022 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -243,6 +243,7 @@ static void conf_merge_group(GKeyFile *conf, GKeyFile *k, const char *group)
group, key, &count, NULL);
key[len-1] = 0;
g_strchomp(key); /* Strip spaces before + */
conf_list_append(conf, k, group, key,
values, count, last == '?');
g_strfreev(values);
@@ -252,6 +253,7 @@ static void conf_merge_group(GKeyFile *conf, GKeyFile *k, const char *group)
group, key, &count, NULL);
key[len-1] = 0;
g_strchomp(key); /* Strip spaces before - */
conf_list_remove(conf, k, group, key,
values, count);
g_strfreev(values);
@@ -531,13 +533,16 @@ gboolean ofono_conf_get_mask(GKeyFile *file, const char *group,
char **values, **ptr;
if (comment) *comment = 0;
values = g_strsplit(str, "+", -1);
values = g_strsplit_set(str, "+,", -1);
for (ok = TRUE, ptr = values; *ptr && ok; ptr++) {
const char* found_str = NULL;
const char* s = g_strstrip(*ptr);
if (!strcasecmp(s, name)) {
if (!s[0]) {
/* Ignore empty entries */
continue;
} else if (!strcasecmp(s, name)) {
found_str = name;
if (result) {
*result |= value;

View File

@@ -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;
}
@@ -188,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_AUTO
};
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

@@ -65,7 +65,9 @@ struct ofono_radio_settings {
enum ofono_radio_access_mode ofono_radio_access_max_mode(
enum ofono_radio_access_mode mask)
{
return (mask & OFONO_RADIO_ACCESS_MODE_LTE) ?
return (mask & OFONO_RADIO_ACCESS_MODE_NR) ?
OFONO_RADIO_ACCESS_MODE_NR :
(mask & OFONO_RADIO_ACCESS_MODE_LTE) ?
OFONO_RADIO_ACCESS_MODE_LTE :
(mask & OFONO_RADIO_ACCESS_MODE_UMTS) ?
OFONO_RADIO_ACCESS_MODE_UMTS :
@@ -86,6 +88,8 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m)
return "umts";
case OFONO_RADIO_ACCESS_MODE_LTE:
return "lte";
case OFONO_RADIO_ACCESS_MODE_NR:
return "nr";
default:
return NULL;
}
@@ -110,6 +114,9 @@ ofono_bool_t ofono_radio_access_mode_from_string(const char *str,
} else if (g_str_equal(str, "lte")) {
*mode = OFONO_RADIO_ACCESS_MODE_LTE;
return TRUE;
} else if (g_str_equal(str, "nr")) {
*mode = OFONO_RADIO_ACCESS_MODE_NR;
return TRUE;
}
return FALSE;
@@ -438,7 +445,7 @@ static void radio_available_rats_query_callback(const struct ofono_error *error,
struct ofono_radio_settings *rs = data;
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
rs->available_rats = available_rats & 0x7;
rs->available_rats = available_rats & 0xF;
else
DBG("Error while querying available rats");

View File

@@ -628,6 +628,10 @@ gboolean sms_decode_address_field(const unsigned char *pdu, int len,
if (!next_octet(pdu, len, offset, &addr_len))
return FALSE;
/* According to 23.040 9.1.2.5 Address-Length must not exceed 20 */
if (addr_len > 20)
return FALSE;
if (sc && addr_len == 0) {
out->address[0] = '\0';
return TRUE;
@@ -779,6 +783,9 @@ static gboolean decode_deliver(const unsigned char *pdu, int len,
expected = sms_udl_in_bytes(out->deliver.udl, out->deliver.dcs);
if (expected < 0 || expected > (int)sizeof(out->deliver.ud))
return FALSE;
if ((len - offset) < expected)
return FALSE;
@@ -941,10 +948,16 @@ static gboolean decode_submit_report(const unsigned char *pdu, int len,
return FALSE;
if (out->type == SMS_TYPE_SUBMIT_REPORT_ERROR) {
if (expected > (int) sizeof(out->submit_err_report.ud))
return FALSE;
out->submit_err_report.udl = udl;
memcpy(out->submit_err_report.ud,
pdu + offset, expected);
} else {
if (expected > (int) sizeof(out->submit_ack_report.ud))
return FALSE;
out->submit_ack_report.udl = udl;
memcpy(out->submit_ack_report.ud,
pdu + offset, expected);
@@ -1077,6 +1090,9 @@ static gboolean decode_status_report(const unsigned char *pdu, int len,
if ((len - offset) < expected)
return FALSE;
if (expected > (int)sizeof(out->status_report.ud))
return FALSE;
memcpy(out->status_report.ud, pdu + offset, expected);
}
@@ -1226,10 +1242,16 @@ static gboolean decode_deliver_report(const unsigned char *pdu, int len,
return FALSE;
if (out->type == SMS_TYPE_DELIVER_REPORT_ERROR) {
if (expected > (int) sizeof(out->deliver_err_report.ud))
return FALSE;
out->deliver_err_report.udl = udl;
memcpy(out->deliver_err_report.ud,
pdu + offset, expected);
} else {
if (expected > (int) sizeof(out->deliver_ack_report.ud))
return FALSE;
out->deliver_ack_report.udl = udl;
memcpy(out->deliver_ack_report.ud,
pdu + offset, expected);
@@ -1464,6 +1486,9 @@ static gboolean decode_command(const unsigned char *pdu, int len,
if ((len - offset) < out->command.cdl)
return FALSE;
if (out->command.cdl > sizeof(out->command.cd))
return FALSE;
memcpy(out->command.cd, pdu + offset, out->command.cdl);
return TRUE;
@@ -4593,13 +4618,11 @@ out:
GSList *cbs_optimize_ranges(GSList *ranges)
{
struct cbs_topic_range *range;
unsigned char bitmap[125];
unsigned char *bitmap = g_malloc0(CBS_MAX_TOPIC / 8 + 1);
GSList *l;
unsigned short i;
GSList *ret = NULL;
memset(bitmap, 0, sizeof(bitmap));
for (l = ranges; l; l = l->next) {
range = l->data;
@@ -4613,7 +4636,7 @@ GSList *cbs_optimize_ranges(GSList *ranges)
range = NULL;
for (i = 0; i <= 999; i++) {
for (i = 0; i <= CBS_MAX_TOPIC; i++) {
int byte_offset = i / 8;
int bit = i % 8;
@@ -4641,6 +4664,7 @@ GSList *cbs_optimize_ranges(GSList *ranges)
ret = g_slist_reverse(ret);
g_free(bitmap);
return ret;
}
@@ -4653,10 +4677,10 @@ GSList *cbs_extract_topic_ranges(const char *ranges)
GSList *tmp;
while (next_range(ranges, &offset, &min, &max) == TRUE) {
if (min < 0 || min > 999)
if (min < 0 || min > CBS_MAX_TOPIC)
return NULL;
if (max < 0 || max > 999)
if (max < 0 || max > CBS_MAX_TOPIC)
return NULL;
if (max < min)

View File

@@ -23,6 +23,7 @@
#include <ofono/types.h>
#define CBS_MAX_GSM_CHARS 93
#define CBS_MAX_TOPIC 9999
#define SMS_MSGID_LEN 20
enum sms_type {

View File

@@ -1816,6 +1816,10 @@ static bool parse_dataobj_frame_layout(struct comprehension_tlv_iter *iter,
fl->layout = data[0];
fl->len = len - 1;
if (fl->len > sizeof(fl->size))
return false;
memcpy(fl->size, data + 1, fl->len);
return true;
@@ -1909,6 +1913,10 @@ static bool parse_dataobj_mms_reference(struct comprehension_tlv_iter *iter,
data = comprehension_tlv_iter_get_data(iter);
mr->len = len;
if (len > sizeof(mr->ref))
return false;
memcpy(mr->ref, data, len);
return true;
@@ -1927,6 +1935,10 @@ static bool parse_dataobj_mms_id(struct comprehension_tlv_iter *iter,
data = comprehension_tlv_iter_get_data(iter);
mi->len = len;
if (len > sizeof(mi->id))
return false;
memcpy(mi->id, data, len);
return true;
@@ -1963,6 +1975,10 @@ static bool parse_dataobj_mms_content_id(
data = comprehension_tlv_iter_get_data(iter);
mci->len = len;
if (len > sizeof(mci->id))
return false;
memcpy(mci->id, data, len);
return true;

View File

@@ -2665,9 +2665,9 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
if (l) {
/* Incoming call was disconnected in the process of being
* filtered. voicecall_destroy cancels it. */
voicecall_destroy(l->data);
vc->incoming_filter_list = g_slist_delete_link
(vc->incoming_filter_list, l);
voicecall_destroy(l->data);
return;
}

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

@@ -92,9 +92,9 @@ def set_topics(cbs):
break
if topicTemp:
if int(topicTemp) > 999:
if int(topicTemp) > 9999:
invalidData = True
print("Invalid Topic ID %s (range 0-999). \
print("Invalid Topic ID %s (range 0-9999). \
\nCould not register." % topicTemp)
index = index + 1

View File

@@ -318,6 +318,28 @@ static struct ofono_cell *test_cell_init_lte(struct ofono_cell *cell)
return cell;
}
static struct ofono_cell *test_cell_init_nr(struct ofono_cell *cell)
{
struct ofono_cell_info_nr *nr = &cell->info.nr;
memset(cell, 0, sizeof(*cell));
cell->type = OFONO_CELL_TYPE_NR;
cell->registered = TRUE;
nr->mcc = 244;
nr->mnc = 91;
nr->nci = 36591883;
nr->pci = 309;
nr->tac = 4030;
nr->nrarfcn = INT_MAX;
nr->ssRsrp = 106;
nr->ssRsrq = 6;
nr->ssSinr = INT_MAX;
nr->csiRsrp = 106;
nr->csiRsrq = 6;
nr->csiSinr = INT_MAX;
return cell;
}
/* ==== Misc ==== */
static void test_misc(void)
@@ -540,6 +562,13 @@ static void test_get_all4(void)
{
struct ofono_cell cell;
test_get_all(test_cell_init_nr(&cell), "nr");
}
static void test_get_all5(void)
{
struct ofono_cell cell;
/* Invalid cell */
memset(&cell, 0xff, sizeof(cell));
test_get_all(&cell, "unknown");
@@ -1145,6 +1174,7 @@ int main(int argc, char *argv[])
g_test_add_func(TEST_("GetAll2"), test_get_all2);
g_test_add_func(TEST_("GetAll3"), test_get_all3);
g_test_add_func(TEST_("GetAll4"), test_get_all4);
g_test_add_func(TEST_("GetAll5"), test_get_all5);
g_test_add_func(TEST_("GetInterfaceVersion"), test_get_version);
g_test_add_func(TEST_("GetType"), test_get_type);
g_test_add_func(TEST_("GetRegistered"), test_get_registered);

View File

@@ -226,6 +226,35 @@ static void test_compare(void)
c2 = c1; c2.info.lte.timingAdvance++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
/* NR */
c1.type = OFONO_CELL_TYPE_NR;
c2 = c1;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.mcc++;
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
c2 = c1; c2.info.nr.mnc++;
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
c2 = c1; c2.info.nr.nci++;
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
c2 = c1; c2.info.nr.pci++;
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
c2 = c1; c2.info.nr.tac++;
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
/* Other attributes are not being compared */
c2 = c1; c2.info.nr.nrarfcn++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.ssRsrp++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.ssRsrq++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.ssSinr++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.csiRsrp++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.csiRsrq++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
c2 = c1; c2.info.nr.csiSinr++;
g_assert(!ofono_cell_compare_location(&c1, &c2));
/* Unknown type */
c1.type = c2.type = (enum ofono_cell_type)-1;
g_assert(!ofono_cell_compare_location(&c1, &c2));

View File

@@ -75,6 +75,7 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
char *file1 = g_strconcat(subdir, "/bar.conf", NULL);
GKeyFile *k = g_key_file_new();
char *data;
char *out_stripped = g_strstrip(g_strdup(out));
g_assert(!mkdir(subdir, 0700));
g_assert(g_file_set_contents(file, conf, -1, NULL));
@@ -84,8 +85,9 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
g_key_file_set_list_separator(k, ',');
ofono_conf_merge_files(k, file);
data = g_key_file_to_data(k, NULL, NULL);
g_strstrip(data);
DBG("\n%s", data);
g_assert(!g_strcmp0(data, out));
g_assert(!g_strcmp0(data, out_stripped));
g_free(data);
g_key_file_unref(k);
@@ -94,6 +96,7 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
remove(subdir);
remove(dir);
g_free(out_stripped);
g_free(file);
g_free(file1);
g_free(dir);

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

@@ -1589,7 +1589,7 @@ static void test_cbs_padding_character(void)
static const char *ranges[] = { "1-5, 2, 3, 600, 569-900, 999",
"0-20, 33, 44, 50-60, 20-50, 1-5, 5, 3, 5",
NULL };
static const char *inv_ranges[] = { "1-5, 3333", "1-5, afbcd", "1-5, 3-5,,",
static const char *inv_ranges[] = { "1-5, 33333", "1-5, afbcd", "1-5, 3-5,,",
"1-5, 3-5, c", NULL };
static void test_range_minimizer(void)

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

View File

@@ -22,7 +22,7 @@ BuildRequires: pkgconfig(rpm)
Requires: dbus
Requires: systemd
Requires: libglibutil >= %{libglibutil_version}
%{recommend}: mobile-broadband-provider-info
Requires: mobile-broadband-provider-info
%{recommend}: ofono-configs
Requires(preun): systemd
Requires(post): systemd