Compare commits

..

12 Commits

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

	string Registration [readwrite, Sailfish OS specific]

		The IMS registration strategy. Valid values are:

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

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

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

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

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

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

View File

@@ -1,9 +1,3 @@
ver 1.29:
Fix issue with QMI and SIM initialized notification.
Add support for multiple PDP contexts and xmm7xxx modems.
Add support for handling Dual SIM Single Active feature
Add support for SIM PIN caching feature.
ver 1.28:
Fix issue with SIM initialization and Gemalto modems.

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
AC_INIT(ofono, 1.29)
AC_INIT(ofono, 1.28)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h)

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

@@ -205,15 +205,3 @@ Properties boolean Present [readonly]
Contains the SIM's ImsPrivateIdentity, read from the
ISIM.
uint32 CardSlotCount [readonly, experimental]
Contains the count of number of SIM card slots available.
uint32 ActiveCardSlot [readwrite, experimental]
Contains the index of the currently active SIM card slot
for dual SIM single active mode.
This property will range from 1 (default) to
CardSlotCount (max) value.

View File

@@ -455,6 +455,7 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
FALSE, gprs, NULL);
break;
case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify,
FALSE, gprs, NULL);
g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix,

View File

@@ -1559,12 +1559,12 @@ static void creg_notify(GAtResult *result, gpointer user_data)
option_query_tech_cb, tq, g_free) > 0)
return;
break;
case OFONO_VENDOR_GEMALTO:
if (g_at_chat_send(nd->chat, "AT^SMONI",
smoni_prefix,
gemalto_query_tech_cb, tq, g_free) > 0)
return;
break;
case OFONO_VENDOR_GEMALTO:
if (g_at_chat_send(nd->chat, "AT^SMONI",
smoni_prefix,
gemalto_query_tech_cb, tq, g_free) > 0)
return;
break;
}
g_free(tq);
@@ -1655,11 +1655,8 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
DBG("");
switch (nd->vendor) {
case OFONO_VENDOR_UBLOX:
/* For all u-blox models, mode 3 is equivalent to mode 1;
* since some models do not support setting modes 2 nor 3
* (see UBX-13002752), we prefer mode 1 for all models.
*/
case OFONO_VENDOR_UBLOX_TOBY_L2:
/* UBX-13002752 R33: TOBY L2 doesn't support mode 2 and 3 */
mode = "1";
break;
default:

View File

@@ -75,7 +75,6 @@ static const char *cuad_prefix[] = { "+CUAD:", NULL };
static const char *ccho_prefix[] = { "+CCHO:", NULL };
static const char *crla_prefix[] = { "+CRLA:", NULL };
static const char *cgla_prefix[] = { "+CGLA:", NULL };
static const char *xcmscsc_prefix[] = { "+XCMSCSC:", NULL};
static const char *none_prefix[] = { NULL };
static void append_file_path(char *buf, const unsigned char *path,
@@ -1161,7 +1160,6 @@ static void at_pin_retries_query(struct ofono_sim *sim,
DBG("");
switch (sd->vendor) {
case OFONO_VENDOR_XMM:
case OFONO_VENDOR_IFX:
if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
xpincnt_cb, cbd, g_free) > 0)
@@ -1223,6 +1221,7 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return;
break;
case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:
if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
upincnt_cb, cbd, g_free) > 0)
return;
@@ -1922,83 +1921,6 @@ static void at_logical_access(struct ofono_sim *sim, int session_id,
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static void xcmscsc_query_cb(gboolean ok, GAtResult *result, gpointer user)
{
struct ofono_sim *sim = user;
struct sim_data *sd = ofono_sim_get_data(sim);
GAtResultIter iter;
int active_slot;
if (!ok)
goto done;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+XCMSCSC:"))
goto done;
g_at_result_iter_skip_next(&iter);
g_at_result_iter_skip_next(&iter);
g_at_result_iter_next_number(&iter, &active_slot);
/* set active SIM slot */
ofono_sim_set_active_card_slot(sim, active_slot + 1);
done:
/* Query supported <fac>s */
g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix,
at_clck_query_cb, sim, NULL);
}
static void at_xcmscsc_test_cb(gboolean ok, GAtResult *result, gpointer user)
{
struct ofono_sim *sim = user;
struct sim_data *sd = ofono_sim_get_data(sim);
GAtResultIter iter;
int card_slot_count;
if (!ok)
goto done;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+XCMSCSC:"))
goto done;
g_at_result_iter_skip_next(&iter);
g_at_result_iter_skip_next(&iter);
if (!g_at_result_iter_open_list(&iter))
goto done;
g_at_result_iter_skip_next(&iter);
if (!g_at_result_iter_next_number(&iter, &card_slot_count))
goto done;
/* Set num slots */
ofono_sim_set_card_slot_count(sim, card_slot_count + 1);
/*
* enable reporting of MSIM remap status information
* and enable automatic acceptance of MSIM Remap
* acknowledgement
*/
g_at_chat_send(sd->chat, "AT+XCMSRS=2", none_prefix,
NULL, NULL, NULL);
/* Query active card slot */
g_at_chat_send(sd->chat, "AT+XCMSCSC?", xcmscsc_prefix,
xcmscsc_query_cb, sim, NULL);
return;
done:
/* Query supported <fac>s */
g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix,
at_clck_query_cb, sim, NULL);
}
static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
void *data)
{
@@ -2017,10 +1939,6 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
if (at_clck_cpwd_fac[i])
sd->passwd_type_mask |= (1 << i);
if (sd->vendor == OFONO_VENDOR_XMM)
return g_at_chat_send(sd->chat, "AT+XCMSCSC=?", xcmscsc_prefix,
at_xcmscsc_test_cb, sim, NULL) ? 0 : -1;
/* Query supported <fac>s */
return g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix,
at_clck_query_cb, sim, NULL) ? 0 : -1;
@@ -2040,46 +1958,6 @@ static void at_sim_remove(struct ofono_sim *sim)
g_free(sd);
}
static void xcmscsc_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_set_active_card_slot_cb_t cb = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
if (cb)
cb(&error, cbd->data);
}
static void at_set_active_card_slot(struct ofono_sim *sim, unsigned int index,
ofono_sim_set_active_card_slot_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char cmd[43];
if (sd->vendor != OFONO_VENDOR_XMM) {
struct ofono_error error;
error.type = OFONO_ERROR_TYPE_CME;
error.error = 4;
cb(&error, data);
return;
}
/* Enable single SIM mode for indicated card slot id */
snprintf(cmd, sizeof(cmd), "AT+XCMSCSC=1,0,%u,1", index);
if (g_at_chat_send(sd->chat, cmd, none_prefix, xcmscsc_cb,
cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static const struct ofono_sim_driver driver = {
.name = "atmodem",
.probe = at_sim_probe,
@@ -2105,8 +1983,7 @@ static const struct ofono_sim_driver driver = {
.session_read_binary = at_session_read_binary,
.session_read_record = at_session_read_record,
.session_read_info = at_session_read_info,
.logical_access = at_logical_access,
.set_active_card_slot = at_set_active_card_slot
.logical_access = at_logical_access
};
static const struct ofono_sim_driver driver_noef = {

View File

@@ -46,6 +46,7 @@ enum ofono_vendor {
OFONO_VENDOR_QUECTEL,
OFONO_VENDOR_QUECTEL_M95,
OFONO_VENDOR_UBLOX,
OFONO_VENDOR_UBLOX_TOBY_L2,
OFONO_VENDOR_XMM,
OFONO_VENDOR_GEMALTO,
};

View File

@@ -260,45 +260,6 @@ error:
failed_setup(gc, NULL, TRUE);
}
static void cgdata_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("ok %d", ok);
if (!ok) {
ofono_error("Failed to establish session");
failed_setup(gc, result, TRUE);
return;
}
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
}
static const char *get_datapath(struct ofono_modem *modem,
const char *interface)
{
static char datapath[256];
char n;
if (!strcmp(interface,
ofono_modem_get_string(modem, "NetworkInterface")))
n = '0';
else if (!strcmp(interface,
ofono_modem_get_string(modem, "NetworkInterface2")))
n = '1';
else if (!strcmp(interface,
ofono_modem_get_string(modem, "NetworkInterface3")))
n = '2';
else
return NULL;
snprintf(datapath, sizeof(datapath), "%s%c",
ofono_modem_get_string(modem, "DataPath"), n);
return datapath;
}
static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
@@ -308,11 +269,8 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
const char *laddrnetmask = NULL;
const char *gw = NULL;
const char *dns[3];
const char *ctrlpath;
const char *datapath;
char buf[512];
const char *interface;
const char *dns[3];
DBG("ok %d", ok);
@@ -369,10 +327,9 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
DBG("DNS2: %s\n", gcd->dns2);
DBG("Gateway: %s\n", gcd->gateway);
ctrlpath = ofono_modem_get_string(modem, "CtrlPath");
interface = ofono_gprs_context_get_interface(gc);
datapath = get_datapath(modem, interface);
interface = ofono_modem_get_string(modem, "NetworkInterface");
ofono_gprs_context_set_interface(gc, interface);
ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE);
if (gcd->netmask[0])
@@ -383,17 +340,7 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
snprintf(buf, sizeof(buf), "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u",
ctrlpath, datapath, gcd->active_context);
g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL);
snprintf(buf, sizeof(buf), "AT+CGDATA=\"M-RAW_IP\",%u",
gcd->active_context);
if (g_at_chat_send(gcd->chat, buf, none_prefix, cgdata_cb,
gc, NULL) > 0)
return;
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
}
static void ifx_read_settings(struct ofono_gprs_context *gc)

View File

@@ -250,7 +250,6 @@ static void process_uim_state(struct ofono_sim *sim, uint8_t state)
switch (state) {
case QMI_DMS_UIM_STATE_INIT_COMPLETE:
ofono_sim_inserted_notify(sim, TRUE);
ofono_sim_initialized_notify(sim);
break;
case QMI_DMS_UIM_STATE_INIT_FAILED:
case QMI_DMS_UIM_STATE_NOT_PRESENT:

View File

@@ -524,7 +524,7 @@ static bool get_card_status(const struct qmi_uim_slot_info *slot,
return need_retry;
}
static enum get_card_status_result handle_get_card_status_data(
static enum get_card_status_result handle_get_card_status_result(
struct qmi_result *result, struct sim_status *sim_stat)
{
const void *ptr;
@@ -533,6 +533,9 @@ static enum get_card_status_result handle_get_card_status_data(
uint8_t i;
enum get_card_status_result res = GET_CARD_STATUS_RESULT_ERROR;
if (qmi_result_set_error(result, NULL))
goto done;
ptr = qmi_result_get(result, QMI_UIM_RESULT_CARD_STATUS, &len);
if (!ptr)
goto done;
@@ -575,15 +578,6 @@ done:
return res;
}
static enum get_card_status_result handle_get_card_status_result(
struct qmi_result *result, struct sim_status *sim_stat)
{
if (qmi_result_set_error(result, NULL))
return GET_CARD_STATUS_RESULT_ERROR;
return handle_get_card_status_data(result, sim_stat);
}
static gboolean query_passwd_state_retry(gpointer userdata)
{
struct cb_data *cbd = userdata;
@@ -795,34 +789,6 @@ static void get_card_status_cb(struct qmi_result *result, void *user_data)
case 0x00: /* Absent */
case 0x02: /* Error */
break;
case 0x01: /* Present */
ofono_sim_inserted_notify(sim, TRUE);
ofono_sim_initialized_notify(sim);
break;
}
}
static void card_status_notify(struct qmi_result *result, void *user_data)
{
struct ofono_sim *sim = user_data;
struct sim_data *data = ofono_sim_get_data(sim);
struct sim_status sim_stat;
DBG("");
if (handle_get_card_status_data(result, &sim_stat) !=
GET_CARD_STATUS_RESULT_OK) {
data->app_type = 0; /* Unknown */
sim_stat.card_state = 0x00; /* Absent */
} else {
data->app_type = sim_stat.app_type;
}
switch (sim_stat.card_state) {
case 0x00: /* Absent */
case 0x02: /* Error */
ofono_sim_inserted_notify(sim, FALSE);
break;
case 0x01: /* Present */
ofono_sim_inserted_notify(sim, TRUE);
break;
@@ -844,9 +810,6 @@ static void event_registration_cb(struct qmi_result *result, void *user_data)
goto error;
DBG("event mask 0x%04x", data->event_mask);
if (data->event_mask & 0x0001)
qmi_service_register(data->uim, QMI_UIM_GET_CARD_STATUS_EVENT,
card_status_notify, sim, NULL);
if (qmi_service_send(data->uim, QMI_UIM_GET_CARD_STATUS, NULL,
get_card_status_cb, sim, NULL) > 0)

View File

@@ -29,7 +29,7 @@
#define QMI_UIM_EVENT_REGISTRATION 46 /* Register for indications */
#define QMI_UIM_GET_CARD_STATUS 47 /* Get card status */
#define QMI_UIM_GET_CARD_STATUS_EVENT 50 /* Card status indication */
/* Register for indications */
#define QMI_UIM_PARAM_EVENT_MASK 0x01 /* uint32 */

View File

@@ -43,20 +43,12 @@
static const char *none_prefix[] = { NULL };
static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL };
static const char *uipaddr_prefix[] = { "+UIPADDR:", NULL };
static const char *ubmconf_prefix[] = { "+UBMCONF:", NULL };
enum netmode {
NETWORKING_MODE_ROUTER,
NETWORKING_MODE_BRIDGE,
};
struct gprs_context_data {
const struct ublox_model *model;
GAtChat *chat;
unsigned int active_context;
ofono_gprs_context_cb_t cb;
void *cb_data;
enum netmode networking_mode;
};
static void uipaddr_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -235,14 +227,6 @@ static void ublox_read_settings(struct ofono_gprs_context *gc)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
if (gcd->networking_mode == NETWORKING_MODE_ROUTER) {
/* Use DHCP */
set_gprs_context_interface(gc);
ofono_gprs_context_set_ipv4_address(gc, NULL, 0);
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
return;
}
if (ublox_send_cgcontrdp(gc) < 0)
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
}
@@ -477,44 +461,8 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
gcd->active_context = 0;
}
static void at_ubmconf_read_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_gprs_context *gc = user_data;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
GAtResultIter iter;
int mode;
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+UBMCONF:"))
goto error;
if (!g_at_result_iter_next_number(&iter, &mode))
goto error;
switch (mode) {
case 1:
gcd->networking_mode = NETWORKING_MODE_ROUTER;
break;
case 2:
gcd->networking_mode = NETWORKING_MODE_BRIDGE;
break;
default:
goto error;
}
return;
error:
ofono_error("AT+UBMCONF? failed; assuming router mode");
gcd->networking_mode = NETWORKING_MODE_ROUTER;
}
static int ublox_gprs_context_probe(struct ofono_gprs_context *gc,
unsigned int model_id, void *data)
unsigned int vendor, void *data)
{
GAtChat *chat = data;
struct gprs_context_data *gcd;
@@ -525,23 +473,10 @@ static int ublox_gprs_context_probe(struct ofono_gprs_context *gc,
if (gcd == NULL)
return -ENOMEM;
gcd->model = ublox_model_from_id(model_id);
if (!gcd->model)
return -EINVAL;
gcd->chat = g_at_chat_clone(chat);
ofono_gprs_context_set_data(gc, gcd);
if (ublox_is_toby_l2(gcd->model)) {
g_at_chat_send(chat, "AT+UBMCONF?", ubmconf_prefix,
at_ubmconf_read_cb, gc, NULL);
} else if (ublox_is_toby_l4(gcd->model)) {
gcd->networking_mode = NETWORKING_MODE_ROUTER;
} else {
gcd->networking_mode = NETWORKING_MODE_ROUTER;
}
g_at_chat_register(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL);
return 0;

View File

@@ -39,85 +39,24 @@
#include "ubloxmodem.h"
static const char *none_prefix[] = { NULL };
static const char *ucgdflt_prefix[] = { "+UCGDFLT:", NULL };
struct lte_driver_data {
GAtChat *chat;
const struct ublox_model *model;
struct ofono_lte_default_attach_info pending_info;
};
static void at_lte_set_auth_cb(gboolean ok, GAtResult *result,
gpointer user_data)
static void ucgdflt_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_lte_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("ok %d", ok);
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void at_lte_set_default_attach_info_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_lte_cb_t cb = cbd->cb;
void *data = cbd->data;
struct lte_driver_data *ldd = cbd->user;
struct ofono_error error;
char buf[32 + OFONO_GPRS_MAX_USERNAME_LENGTH +
OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
enum ofono_gprs_auth_method auth_method;
int cid;
if (!ok) {
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, data);
return;
}
if (ublox_is_toby_l2(ldd->model)) {
/* If CGDCONT has already been used to set up cid 4 then
* the EPS default bearer will be configured from another
* cid (see documentation for how this is selected). Avoid
* doing so as this assumes as much...
*/
cid = 4;
} else if (ublox_is_toby_l4(ldd->model)) {
cid = 1;
} else {
ofono_error("Unknown model; "
"unable to determine EPS default bearer CID");
goto out;
}
auth_method = ldd->pending_info.auth_method;
/* change the authentication method if the parameters are invalid */
if (!*ldd->pending_info.username || !*ldd->pending_info.password)
auth_method = OFONO_GPRS_AUTH_METHOD_NONE;
/* In contrast to CGAUTH, all four parameters are _required_ here;
* if auth type is NONE then username and password must be set to
* empty strings.
*/
sprintf(buf, "AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"",
cid,
at_util_gprs_auth_method_to_auth_prot(auth_method),
ldd->pending_info.username,
ldd->pending_info.password);
cbd = cb_data_ref(cbd);
if (g_at_chat_send(ldd->chat, buf, none_prefix,
at_lte_set_auth_cb, cbd, cb_data_unref) > 0)
return;
out:
cb_data_unref(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void ublox_lte_set_default_attach_info(const struct ofono_lte *lte,
const struct ofono_lte_default_attach_info *info,
ofono_lte_cb_t cb, void *data)
@@ -128,32 +67,17 @@ static void ublox_lte_set_default_attach_info(const struct ofono_lte *lte,
DBG("LTE config with APN: %s", info->apn);
cbd->user = ldd;
memcpy(&ldd->pending_info, info, sizeof(ldd->pending_info));
if (ublox_is_toby_l2(ldd->model)) {
if (strlen(info->apn) > 0)
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,%s,\"%s\"",
at_util_gprs_proto_to_pdp_type(info->proto),
if (strlen(info->apn) > 0)
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,\"IP\",\"%s\"",
info->apn);
else
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0");
else
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0");
} else if (ublox_is_toby_l4(ldd->model)) {
if (strlen(info->apn) > 0)
snprintf(buf, sizeof(buf), "AT+CGDCONT=1,%s,\"%s\"",
at_util_gprs_proto_to_pdp_type(info->proto),
info->apn);
else
snprintf(buf, sizeof(buf), "AT+CGDCONT=1");
}
if (g_at_chat_send(ldd->chat, buf, none_prefix,
at_lte_set_default_attach_info_cb,
cbd, cb_data_unref) > 0)
/* We can't do much in case of failure so don't check response. */
if (g_at_chat_send(ldd->chat, buf, ucgdflt_prefix,
ucgdflt_cb, cbd, g_free) > 0)
return;
cb_data_unref(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
@@ -167,7 +91,7 @@ static gboolean lte_delayed_register(gpointer user_data)
}
static int ublox_lte_probe(struct ofono_lte *lte,
unsigned int model_id, void *data)
unsigned int vendor, void *data)
{
GAtChat *chat = data;
struct lte_driver_data *ldd;
@@ -179,7 +103,6 @@ static int ublox_lte_probe(struct ofono_lte *lte,
return -ENOMEM;
ldd->chat = g_at_chat_clone(chat);
ldd->model = ublox_model_from_id(model_id);
ofono_lte_set_data(lte, ldd);

View File

@@ -23,8 +23,6 @@
#include <config.h>
#endif
#include <string.h>
#include <glib.h>
#include <gatchat.h>
@@ -35,83 +33,6 @@
#include "ubloxmodem.h"
const struct ublox_model ublox_models[] = {
{
.name = "SARA-G270",
},
/* TOBY L2 series */
{
.name = "TOBY-L200",
.flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF,
},
{
.name = "TOBY-L201",
.flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF,
},
{
.name = "TOBY-L210",
.flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF,
},
{
.name = "TOBY-L220",
.flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF,
},
{
.name = "TOBY-L280",
.flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF,
},
/* TOBY L4 series */
{
.name = "TOBY-L4006",
.flags = UBLOX_F_TOBY_L4,
},
{
.name = "TOBY-L4106",
.flags = UBLOX_F_TOBY_L4,
},
{
.name = "TOBY-L4206",
.flags = UBLOX_F_TOBY_L4,
},
{
.name = "TOBY-L4906",
.flags = UBLOX_F_TOBY_L4,
},
{ /* sentinel */ },
};
const struct ublox_model *ublox_model_from_name(const char *name)
{
const struct ublox_model *m;
for (m = ublox_models; m->name; m++) {
if (!strcmp(name, m->name))
return m;
}
return NULL;
}
const struct ublox_model *ublox_model_from_id(int id)
{
return ublox_models + id;
}
int ublox_model_to_id(const struct ublox_model *model)
{
return model - ublox_models;
}
int ublox_is_toby_l2(const struct ublox_model *model)
{
return model->flags & UBLOX_F_TOBY_L2;
}
int ublox_is_toby_l4(const struct ublox_model *model)
{
return model->flags & UBLOX_F_TOBY_L4;
}
static int ubloxmodem_init(void)
{
ublox_gprs_context_init();

View File

@@ -23,23 +23,6 @@
#define UBLOXMODEM "ubloxmodem"
enum ublox_flags {
UBLOX_F_TOBY_L2 = (1 << 0),
UBLOX_F_TOBY_L4 = (1 << 1),
UBLOX_F_HAVE_USBCONF = (1 << 2),
};
struct ublox_model {
char *name;
int flags;
};
const struct ublox_model *ublox_model_from_name(const char *name);
const struct ublox_model *ublox_model_from_id(int id);
int ublox_model_to_id(const struct ublox_model *model);
int ublox_is_toby_l2(const struct ublox_model *model);
int ublox_is_toby_l4(const struct ublox_model *model);
extern void ublox_gprs_context_init(void);
extern void ublox_gprs_context_exit(void);

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

@@ -93,8 +93,6 @@ void ofono_gprs_context_set_type(struct ofono_gprs_context *gc,
enum ofono_gprs_context_type ofono_gprs_context_get_type(
struct ofono_gprs_context *gc);
const char *ofono_gprs_context_get_interface(struct ofono_gprs_context *gc);
void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc,
const char *interface);

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2022 Jolla Ltd.
* Copyright (C) 2015-2021 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
@@ -138,10 +138,6 @@ typedef void (*ofono_sim_close_channel_cb_t)(const struct ofono_error *error,
typedef void (*ofono_sim_logical_access_cb_t)(const struct ofono_error *error,
const unsigned char *resp, unsigned int len, void *data);
typedef void (*ofono_sim_set_active_card_slot_cb_t)(
const struct ofono_error *error,
void *data);
struct ofono_sim_driver {
const char *name;
int (*probe)(struct ofono_sim *sim, unsigned int vendor, void *data);
@@ -215,23 +211,15 @@ struct ofono_sim_driver {
void (*logical_access)(struct ofono_sim *sim, int session_id,
const unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data);
/* API version 1 (since 1.23+git28) */
/* Since mer/1.23+git28 */
void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid,
unsigned int len, ofono_sim_open_channel_cb_t cb,
void *data);
/* API version 2 (since 1.29+git1) */
void (*set_active_card_slot)(struct ofono_sim *sim, unsigned int index,
ofono_sim_set_active_card_slot_cb_t cb, void *data);
};
int ofono_sim_driver_register(const struct ofono_sim_driver *d);
void ofono_sim_driver_unregister(const struct ofono_sim_driver *d);
#define OFONO_SIM_DRIVER_API_VERSION 2
#define ofono_sim_driver_register(d) /* Since 1.28+git4 */ \
ofono_sim_driver_register_version(d, OFONO_SIM_DRIVER_API_VERSION)
int ofono_sim_driver_register_version(const struct ofono_sim_driver *d, int v);
struct ofono_sim *ofono_sim_create(struct ofono_modem *modem,
unsigned int vendor,
const char *driver, void *data);
@@ -241,9 +229,6 @@ void ofono_sim_remove(struct ofono_sim *sim);
void ofono_sim_set_data(struct ofono_sim *sim, void *data);
void *ofono_sim_get_data(struct ofono_sim *sim);
void ofono_sim_set_card_slot_count(struct ofono_sim *sim, unsigned int val);
void ofono_sim_set_active_card_slot(struct ofono_sim *sim,
unsigned int val);
const char *ofono_sim_get_imsi(struct ofono_sim *sim);
const char *ofono_sim_get_mcc(struct ofono_sim *sim);
@@ -256,8 +241,8 @@ const unsigned char *ofono_sim_get_cphs_service_table(struct ofono_sim *sim);
enum ofono_sim_password_type ofono_sim_get_password_type(struct ofono_sim *sim);
void ofono_sim_refresh_full(struct ofono_sim *sim); /* Since 1.24+git2 */
enum ofono_sim_password_type ofono_sim_puk2pin( /* Since 1.24+git2 */
void ofono_sim_refresh_full(struct ofono_sim *sim); /* Since mer/1.24+git2 */
enum ofono_sim_password_type ofono_sim_puk2pin( /* Since mer/1.24+git2 */
enum ofono_sim_password_type type);
unsigned int ofono_sim_add_state_watch(struct ofono_sim *sim,

View File

@@ -55,9 +55,7 @@ enum ofono_access_technology {
OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA = 4,
OFONO_ACCESS_TECHNOLOGY_UTRAN_HSUPA = 5,
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_EUTRAN = 7
};
/* 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

@@ -115,7 +115,7 @@ static void check_model(gboolean ok, GAtResult *result, gpointer user_data)
if (strstr(model, "SIM800"))
data->modem_type = SIM800;
else if (strstr(model, "SIM900"))
data->modem_type = SIM900;
data->modem_type = SIM800;
else
data->modem_type = SIMCOM_UNKNOWN;
}

View File

@@ -42,24 +42,23 @@
#include <ofono/lte.h>
#include <ofono/voicecall.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/atmodem/vendor.h>
#include <drivers/ubloxmodem/ubloxmodem.h>
static const char *uusbconf_prefix[] = { "+UUSBCONF:", NULL };
static const char *none_prefix[] = { NULL };
enum ublox_device_flags {
UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE = (1 << 0),
enum supported_models {
SARA_G270 = 1102,
TOBYL2_COMPATIBLE_MODE = 1141,
TOBYL2_MEDIUM_THROUGHPUT_MODE = 1143,
TOBYL2_HIGH_THROUGHPUT_MODE = 1146,
};
struct ublox_data {
GAtChat *modem;
GAtChat *aux;
int model_id;
enum ofono_vendor vendor_family;
const struct ublox_model *model;
int flags;
};
static void ublox_debug(const char *str, void *user_data)
@@ -145,151 +144,77 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
return;
}
if (data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE)
/* use bridged mode until routed mode support is added */
g_at_chat_send(data->aux, "AT+UBMCONF=2", none_prefix,
NULL, NULL, NULL);
ofono_modem_set_powered(modem, TRUE);
}
static void query_usbconf_cb(gboolean ok,
GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ublox_data *data = ofono_modem_get_data(modem);
GAtResultIter iter;
int profile;
if (!ok) {
ofono_error("Unable to query USB configuration");
goto error;
}
g_at_result_iter_init(&iter, result);
retry:
if (!g_at_result_iter_next(&iter, "+UUSBCONF:")) {
ofono_error("Unable to query USB configuration");
goto error;
}
if (!g_at_result_iter_next_number(&iter, &profile))
goto retry;
switch (profile) {
case 0: /* Fairly back compatible */
case 1: /* Fairly back compatible plus audio */
break;
case 2: /* Low/medium throughput */
ofono_error("Medium throughput mode not supported");
goto error;
case 3: /* High throughput mode */
data->flags |= UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE;
break;
default:
ofono_error("Unexpected USB profile: %d", profile);
goto error;
}
if (g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
cfun_enable, modem, NULL))
return;
error:
g_at_chat_unref(data->aux);
data->aux = NULL;
g_at_chat_unref(data->modem);
data->modem = NULL;
ofono_modem_set_powered(modem, FALSE);
}
static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ublox_data *data = ofono_modem_get_data(modem);
struct ofono_error error;
const char *model;
const struct ublox_model *m;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok)
goto fail;
if (at_util_parse_attr(result, "", &model) == FALSE) {
ofono_error("Failed to query modem model");
goto fail;
}
m = ublox_model_from_name(model);
if (!m) {
ofono_error("Unrecognized model: %s", model);
goto fail;
}
data->model = m;
DBG("Model: %s", data->model->name);
data->vendor_family = OFONO_VENDOR_UBLOX;
if (data->model->flags & UBLOX_F_HAVE_USBCONF) {
if (g_at_chat_send(data->aux, "AT+UUSBCONF?", uusbconf_prefix,
query_usbconf_cb, modem, NULL))
return;
ofono_error("Unable to query USB configuration");
goto fail;
}
if (g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
cfun_enable, modem, NULL))
return;
fail:
g_at_chat_unref(data->aux);
data->aux = NULL;
g_at_chat_unref(data->modem);
data->modem = NULL;
ofono_modem_set_powered(modem, FALSE);
}
static int ublox_enable(struct ofono_modem *modem)
{
struct ublox_data *data = ofono_modem_get_data(modem);
const char *model_str = NULL;
DBG("%p", modem);
data->aux = open_device(modem, "Aux", "Aux: ");
/* If this is a serial modem then the device may be behind
* the 'Device' attribute instead...
model_str = ofono_modem_get_string(modem, "Model");
if (model_str == NULL)
return -EINVAL;
/*
* Toby L2 devices are more complex and special than previously
* supported U-Blox devices. So they need a vendor of their own.
*/
if (data->aux == NULL) {
data->aux = open_device(modem, "Device", "Aux: ");
if (data->aux == NULL)
return -EINVAL;
data->model_id = atoi(model_str);
switch (data->model_id) {
case SARA_G270:
data->vendor_family = OFONO_VENDOR_UBLOX;
break;
case TOBYL2_COMPATIBLE_MODE:
case TOBYL2_HIGH_THROUGHPUT_MODE:
data->vendor_family = OFONO_VENDOR_UBLOX_TOBY_L2;
break;
case TOBYL2_MEDIUM_THROUGHPUT_MODE:
DBG("low/medium throughtput profile unsupported");
break;
default:
DBG("unknown ublox model id %d", data->model_id);
return -EINVAL;
}
data->modem = open_device(modem, "Modem", "Modem: ");
if (data->modem) {
data->aux = open_device(modem, "Aux", "Aux: ");
if (data->aux == NULL)
return -EINVAL;
if (data->vendor_family == OFONO_VENDOR_UBLOX) {
data->modem = open_device(modem, "Modem", "Modem: ");
if (data->modem == NULL) {
g_at_chat_unref(data->aux);
data->aux = NULL;
return -EIO;
}
g_at_chat_set_slave(data->modem, data->aux);
g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->modem, "AT&C0", NULL, NULL, NULL, NULL);
}
/* The modem can take a while to wake up if just powered on. */
g_at_chat_set_wakeup_command(data->aux, "AT\r", 1000, 11000);
g_at_chat_send(data->aux, "ATE0", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(data->aux, "AT+CMEE=1", none_prefix,
g_at_chat_send(data->aux, "ATE0 +CMEE=1", none_prefix,
NULL, NULL, NULL);
if (g_at_chat_send(data->aux, "AT+CGMM", NULL,
query_model_cb, modem, NULL) > 0)
return -EINPROGRESS;
g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
cfun_enable, modem, NULL);
g_at_chat_unref(data->aux);
data->aux = NULL;
return -EINVAL;
return -EINPROGRESS;
}
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
@@ -383,34 +308,19 @@ static void ublox_post_sim(struct ofono_modem *modem)
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
GAtChat *chat = data->modem ? data->modem : data->aux;
const char *driver;
const char *driver = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ?
"ubloxmodem" : "atmodem";
/* Toby L2: Create same number of contexts as supported PDP contexts. */
int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1;
int variant;
int ncontexts = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ? 8 : 1;
DBG("%p", modem);
gprs = ofono_gprs_create(modem, data->vendor_family, "atmodem",
data->aux);
if (ublox_is_toby_l4(data->model)) {
driver = "ubloxmodem";
variant = ublox_model_to_id(data->model);
} else if (ublox_is_toby_l2(data->model)) {
if (data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE) {
driver = "ubloxmodem";
variant = ublox_model_to_id(data->model);
} else {
driver = "atmodem";
variant = OFONO_VENDOR_UBLOX;
}
} else {
driver = "atmodem";
variant = OFONO_VENDOR_UBLOX;
}
while (ncontexts) {
gc = ofono_gprs_context_create(modem, variant, driver, chat);
gc = ofono_gprs_context_create(modem, data->vendor_family,
driver, chat);
if (gprs && gc)
ofono_gprs_add_context(gprs, gc);
@@ -418,8 +328,7 @@ static void ublox_post_sim(struct ofono_modem *modem)
--ncontexts;
}
ofono_lte_create(modem,
ublox_model_to_id(data->model), "ubloxmodem", data->aux);
ofono_lte_create(modem, 0, "ubloxmodem", data->aux);
}
static void ublox_post_online(struct ofono_modem *modem)

View File

@@ -1090,17 +1090,11 @@ static gboolean setup_ublox(struct modem_info *modem)
* - high throughput profile : 224/1/3
*/
} else if (g_strcmp0(info->interface, "2/2/1") == 0) {
if (!g_strcmp0(modem->model, "1010")) {
if (g_strcmp0(info->number, "06") == 0)
aux = info->devnode;
} else {
if (g_strcmp0(info->number, "02") == 0)
aux = info->devnode;
}
if (g_strcmp0(info->number, "00") == 0)
if (g_strcmp0(info->number, "02") == 0)
aux = info->devnode;
else if (g_strcmp0(info->number, "00") == 0)
mdm = info->devnode;
} else if (g_strcmp0(info->interface, "2/6/0") == 0 ||
g_strcmp0(info->interface, "2/13/0") == 0 ||
g_strcmp0(info->interface, "10/0/0") == 0 ||
g_strcmp0(info->interface, "224/1/3") == 0) {
net = info->devnode;
@@ -1117,6 +1111,7 @@ static gboolean setup_ublox(struct modem_info *modem)
ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_string(modem->modem, "Modem", mdm);
ofono_modem_set_string(modem->modem, "Model", modem->model);
ofono_modem_set_string(modem->modem, "NetworkInterface", net);
return TRUE;
@@ -1184,7 +1179,7 @@ static gboolean setup_gemalto(struct modem_info* modem)
static gboolean setup_xmm7xxx(struct modem_info *modem)
{
const char *mdm = NULL, *net = NULL, *net2 = NULL, *net3 = NULL;
const char *mdm = NULL, *net = NULL;
GSList *list;
DBG("%s %s %s %s %s %s\n", modem->syspath, modem->devname,
@@ -1204,10 +1199,6 @@ static gboolean setup_xmm7xxx(struct modem_info *modem)
} else if (g_strcmp0(info->subsystem, "net") == 0) {
if (g_strcmp0(info->number, "06") == 0)
net = info->devnode;
if (g_strcmp0(info->number, "08") == 0)
net2 = info->devnode;
if (g_strcmp0(info->number, "0a") == 0)
net3 = info->devnode;
}
} else {
if (g_strcmp0(info->subsystem, "tty") == 0) {
@@ -1228,15 +1219,6 @@ static gboolean setup_xmm7xxx(struct modem_info *modem)
ofono_modem_set_string(modem->modem, "Modem", mdm);
ofono_modem_set_string(modem->modem, "NetworkInterface", net);
if (net2)
ofono_modem_set_string(modem->modem, "NetworkInterface2", net2);
if (net3)
ofono_modem_set_string(modem->modem, "NetworkInterface3", net3);
ofono_modem_set_string(modem->modem, "CtrlPath", "/USBCDC/0");
ofono_modem_set_string(modem->modem, "DataPath", "/USBHS/NCM/");
return TRUE;
}
@@ -1696,8 +1678,6 @@ static struct {
{ "quectelqmi", "qcserial", "2c7c", "0121" },
{ "quectelqmi", "qmi_wwan", "2c7c", "0125" },
{ "quectelqmi", "qcserial", "2c7c", "0125" },
{ "ublox", "cdc_acm", "1546", "1010" },
{ "ublox", "cdc_ncm", "1546", "1010" },
{ "ublox", "cdc_acm", "1546", "1102" },
{ "ublox", "rndis_host", "1546", "1146" },
{ "ublox", "cdc_acm", "1546", "1146" },

View File

@@ -1223,7 +1223,7 @@ static void xmm7xxx_pre_sim(struct ofono_modem *modem)
DBG("%p", modem);
ofono_devinfo_create(modem, OFONO_VENDOR_IFX, "atmodem", data->chat);
data->sim = ofono_sim_create(modem, OFONO_VENDOR_XMM, "atmodem",
data->sim = ofono_sim_create(modem, OFONO_VENDOR_IFX, "atmodem",
data->chat);
}
@@ -1269,7 +1269,6 @@ static void xmm7xxx_post_online(struct ofono_modem *modem)
struct xmm7xxx_data *data = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
const char *interface = NULL;
DBG("%p", modem);
@@ -1277,39 +1276,11 @@ static void xmm7xxx_post_online(struct ofono_modem *modem)
gprs = ofono_gprs_create(modem, OFONO_VENDOR_IFX, "atmodem",
data->chat);
interface = ofono_modem_get_string(modem, "NetworkInterface");
gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM, "ifxmodem",
data->chat);
if (gprs && gc) {
if (gprs && gc)
ofono_gprs_add_context(gprs, gc);
ofono_gprs_context_set_interface(gc, interface);
}
interface = ofono_modem_get_string(modem, "NetworkInterface2");
if (interface) {
gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM,
"ifxmodem", data->chat);
if (gprs && gc) {
ofono_gprs_add_context(gprs, gc);
ofono_gprs_context_set_interface(gc, interface);
}
}
interface = ofono_modem_get_string(modem, "NetworkInterface3");
if (interface) {
gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM,
"ifxmodem", data->chat);
if (gprs && gc) {
ofono_gprs_add_context(gprs, gc);
ofono_gprs_context_set_interface(gc, interface);
}
}
ofono_ims_create(modem, "xmm7modem", data->chat);
ofono_netmon_create(modem, 0, "xmm7modem", data->chat);

View File

@@ -706,14 +706,8 @@ const char *registration_tech_to_string(enum ofono_access_technology tech)
return "hspa";
case ACCESS_TECHNOLOGY_EUTRAN:
return "lte";
case ACCESS_TECHNOLOGY_NB_IOT_M1:
return "lte-cat-m1";
case ACCESS_TECHNOLOGY_NB_IOT_NB1:
return "lte-cat-nb1";
case OFONO_ACCESS_TECHNOLOGY_NONE:
break;
default:
return "";
}
return "";
}

View File

@@ -42,10 +42,6 @@
OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA /* 6 */
#define ACCESS_TECHNOLOGY_EUTRAN \
OFONO_ACCESS_TECHNOLOGY_EUTRAN /* 7 */
#define ACCESS_TECHNOLOGY_NB_IOT_M1 \
OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 /* 8 */
#define ACCESS_TECHNOLOGY_NB_IOT_NB1 \
OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 /* 9 */
/* 27.007 Section 7.2 <stat> */
#define NETWORK_REGISTRATION_STATUS_NOT_REGISTERED \

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

@@ -110,6 +110,7 @@ struct ipv6_settings {
};
struct context_settings {
char *interface;
struct ipv4_settings *ipv4;
struct ipv6_settings *ipv6;
};
@@ -120,7 +121,6 @@ struct ofono_gprs_context {
ofono_bool_t inuse;
const struct ofono_gprs_context_driver *driver;
void *driver_data;
char *interface;
struct context_settings *settings;
struct ofono_atom *atom;
};
@@ -361,10 +361,12 @@ static void context_settings_free(struct context_settings *settings)
g_free(settings->ipv6);
settings->ipv6 = NULL;
}
g_free(settings->interface);
settings->interface = NULL;
}
static void context_settings_append_ipv4(struct context_settings *settings,
const char *interface,
DBusMessageIter *iter)
{
DBusMessageIter variant;
@@ -389,7 +391,7 @@ static void context_settings_append_ipv4(struct context_settings *settings,
goto done;
ofono_dbus_dict_append(&array, "Interface",
DBUS_TYPE_STRING, &interface);
DBUS_TYPE_STRING, &settings->interface);
if (settings->ipv4->proxy)
ofono_dbus_dict_append(&array, "Proxy", DBUS_TYPE_STRING,
@@ -431,7 +433,6 @@ done:
}
static void context_settings_append_ipv4_dict(struct context_settings *settings,
const char *interface,
DBusMessageIter *dict)
{
DBusMessageIter entry;
@@ -442,13 +443,12 @@ static void context_settings_append_ipv4_dict(struct context_settings *settings,
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
context_settings_append_ipv4(settings, interface, &entry);
context_settings_append_ipv4(settings, &entry);
dbus_message_iter_close_container(dict, &entry);
}
static void context_settings_append_ipv6(struct context_settings *settings,
const char *interface,
DBusMessageIter *iter)
{
DBusMessageIter variant;
@@ -472,7 +472,7 @@ static void context_settings_append_ipv6(struct context_settings *settings,
goto done;
ofono_dbus_dict_append(&array, "Interface",
DBUS_TYPE_STRING, &interface);
DBUS_TYPE_STRING, &settings->interface);
if (settings->ipv6->ip)
ofono_dbus_dict_append(&array, "Address", DBUS_TYPE_STRING,
@@ -503,7 +503,6 @@ done:
}
static void context_settings_append_ipv6_dict(struct context_settings *settings,
const char *interface,
DBusMessageIter *dict)
{
DBusMessageIter entry;
@@ -514,14 +513,13 @@ static void context_settings_append_ipv6_dict(struct context_settings *settings,
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
context_settings_append_ipv6(settings, interface, &entry);
context_settings_append_ipv6(settings, &entry);
dbus_message_iter_close_container(dict, &entry);
}
static void signal_settings(struct pri_context *ctx, const char *prop,
void (*append)(struct context_settings *,
const char *, DBusMessageIter *))
void (*append)(struct context_settings *, DBusMessageIter *))
{
DBusConnection *conn = ofono_dbus_get_connection();
@@ -529,7 +527,6 @@ static void signal_settings(struct pri_context *ctx, const char *prop,
DBusMessage *signal;
DBusMessageIter iter;
struct context_settings *settings;
const char *interface;
signal = dbus_message_new_signal(path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
@@ -541,15 +538,12 @@ static void signal_settings(struct pri_context *ctx, const char *prop,
dbus_message_iter_init_append(signal, &iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &prop);
if (ctx->context_driver) {
if (ctx->context_driver)
settings = ctx->context_driver->settings;
interface = ctx->context_driver->interface;
} else {
else
settings = NULL;
interface = NULL;
}
append(settings, interface, &iter);
append(settings, &iter);
g_dbus_send_message(conn, signal);
}
@@ -787,16 +781,18 @@ static void pri_setproxy(const char *interface, const char *proxy)
static void pri_reset_context_settings(struct pri_context *ctx)
{
struct context_settings *settings;
const char *interface;
char *interface;
gboolean signal_ipv4;
gboolean signal_ipv6;
if (ctx->context_driver == NULL)
return;
interface = ctx->context_driver->interface;
settings = ctx->context_driver->settings;
interface = settings->interface;
settings->interface = NULL;
signal_ipv4 = settings->ipv4 != NULL;
signal_ipv6 = settings->ipv6 != NULL;
@@ -813,6 +809,8 @@ static void pri_reset_context_settings(struct pri_context *ctx)
}
pri_ifupdown(interface, FALSE);
g_free(interface);
}
static void pri_update_mms_context_settings(struct pri_context *ctx)
@@ -828,10 +826,10 @@ static void pri_update_mms_context_settings(struct pri_context *ctx)
DBG("proxy %s port %u", ctx->proxy_host, ctx->proxy_port);
pri_set_ipv4_addr(gc->interface, settings->ipv4->ip);
pri_set_ipv4_addr(settings->interface, settings->ipv4->ip);
if (ctx->proxy_host)
pri_setproxy(gc->interface, ctx->proxy_host);
pri_setproxy(settings->interface, ctx->proxy_host);
}
static gboolean pri_str_changed(const char *val, const char *newval)
@@ -1058,7 +1056,6 @@ static void append_context_properties(struct pri_context *ctx,
dbus_bool_t value;
const char *strvalue;
struct context_settings *settings;
const char *interface;
ofono_dbus_dict_append(dict, "Name", DBUS_TYPE_STRING, &name);
@@ -1095,16 +1092,13 @@ static void append_context_properties(struct pri_context *ctx,
DBUS_TYPE_STRING, &strvalue);
}
if (ctx->context_driver) {
if (ctx->context_driver)
settings = ctx->context_driver->settings;
interface = ctx->context_driver->interface;
} else {
else
settings = NULL;
interface = NULL;
}
context_settings_append_ipv4_dict(settings, interface, dict);
context_settings_append_ipv6_dict(settings, interface, dict);
context_settings_append_ipv4_dict(settings, dict);
context_settings_append_ipv6_dict(settings, dict);
}
static DBusMessage *pri_get_properties(DBusConnection *conn,
@@ -1153,8 +1147,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
__ofono_dbus_pending_reply(&ctx->pending,
dbus_message_new_method_return(ctx->pending));
if (gc->interface != NULL) {
pri_ifupdown(gc->interface, TRUE);
if (gc->settings->interface != NULL) {
pri_ifupdown(gc->settings->interface, TRUE);
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
gc->settings->ipv4)
@@ -1247,8 +1241,8 @@ static void pri_read_settings_callback(const struct ofono_error *error,
pri_ctx->active = TRUE;
if (gc->interface != NULL) {
pri_ifupdown(gc->interface, TRUE);
if (gc->settings->interface != NULL) {
pri_ifupdown(gc->settings->interface, TRUE);
pri_context_signal_settings(pri_ctx, gc->settings->ipv4 != NULL,
gc->settings->ipv6 != NULL);
@@ -1816,7 +1810,7 @@ static gboolean context_dbus_unregister(struct pri_context *ctx)
if (ctx->active == TRUE) {
const char *interface =
ctx->context_driver->interface;
ctx->context_driver->settings->interface;
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS)
pri_set_ipv4_addr(interface, NULL);
@@ -3301,16 +3295,13 @@ enum ofono_gprs_context_type ofono_gprs_context_get_type(
return gc->type;
}
const char *ofono_gprs_context_get_interface(struct ofono_gprs_context *gc)
{
return gc->interface;
}
void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc,
const char *interface)
{
g_free(gc->interface);
gc->interface = g_strdup(interface);
struct context_settings *settings = gc->settings;
g_free(settings->interface);
settings->interface = g_strdup(interface);
}
void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc,

View File

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

View File

@@ -1150,9 +1150,6 @@ static DBusMessage *modem_set_property(DBusConnection *conn,
if (modem->lockdown)
return __ofono_error_access_denied(msg);
if (!powered)
__ofono_sim_clear_cached_pins(modem->sim);
err = set_powered(modem, powered);
if (err < 0) {
if (err != -EINPROGRESS)

View File

@@ -428,7 +428,6 @@ const struct sim_aid *__ofono_sim_session_get_aid(
struct ofono_sim_aid_session *session);
const char *__ofono_sim_get_impi(struct ofono_sim *sim);
void __ofono_sim_clear_cached_pins(struct ofono_sim *sim);
#include <ofono/stk.h>

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2022 Jolla Ltd.
* Copyright (C) 2015-2021 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
@@ -132,10 +132,6 @@ struct ofono_sim {
struct ofono_atom *atom;
unsigned int hfp_watch;
unsigned int card_slot_count;
unsigned int active_card_slot;
unsigned int pending_active_card_slot;
GSList *aid_sessions;
GSList *aid_list;
char *impi;
@@ -148,11 +144,6 @@ struct ofono_sim {
bool wait_initialized : 1;
};
struct cached_pin {
char *id;
char *pin;
};
struct msisdn_set_request {
struct ofono_sim *sim;
int pending;
@@ -184,18 +175,10 @@ static const char *const passwd_name[] = {
[OFONO_SIM_PASSWORD_PHCORP_PUK] = "corppuk",
};
#undef ofono_sim_driver_register
struct ofono_sim_driver_data {
struct ofono_sim_driver driver; /* Must be first */
const struct ofono_sim_driver *d;
};
static void sim_own_numbers_update(struct ofono_sim *sim);
static GSList *g_drivers = NULL;
static GSList *cached_pins = NULL;
static const char *sim_passwd_name(enum ofono_sim_password_type type)
{
return passwd_name[type];
@@ -575,13 +558,6 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
get_pin_retries(sim, &pin_retries_dict, &dbus_retries);
ofono_dbus_dict_append_dict(&dict, "Retries", DBUS_TYPE_BYTE,
&pin_retries_dict);
ofono_dbus_dict_append(&dict, "CardSlotCount", DBUS_TYPE_UINT32,
&sim->card_slot_count);
ofono_dbus_dict_append(&dict, "ActiveCardSlot", DBUS_TYPE_UINT32,
&sim->active_card_slot);
g_free(pin_retries_dict);
g_free(dbus_retries);
@@ -591,72 +567,6 @@ done:
return reply;
}
static struct cached_pin *pin_cache_lookup(const char *iccid)
{
struct cached_pin *c;
GSList *l;
if (cached_pins == NULL)
return NULL;
for (l = cached_pins; l; l = l->next) {
c = l->data;
if (g_strcmp0(iccid, c->id) == 0)
return c;
}
return NULL;
}
static void pin_cache_update(const char *iccid, const char *pin)
{
struct cached_pin *pin_cached = pin_cache_lookup(iccid);
struct cached_pin *cpins;
if (pin_cached != NULL) {
g_free(pin_cached->pin);
pin_cached->pin = g_strdup(pin);
return;
}
cpins = g_new0(struct cached_pin, 1);
cpins->id = g_strdup(iccid);
cpins->pin = g_strdup(pin);
cached_pins = g_slist_prepend(cached_pins, cpins);
}
static void pin_cache_remove(const char *iccid)
{
struct cached_pin *pin_cached = pin_cache_lookup(iccid);
if (pin_cached == NULL)
return;
cached_pins = g_slist_remove(cached_pins, pin_cached);
g_free(pin_cached->pin);
g_free(pin_cached->id);
g_free(pin_cached);
}
static void pin_cache_enter_cb(const struct ofono_error *error, void *data)
{
struct ofono_sim *sim = data;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
pin_cache_remove(sim->iccid);
__ofono_sim_recheck_pin(sim);
return;
}
sim->wait_initialized = true;
DBG("Waiting for ofono_sim_initialized_notify");
}
static void sim_pin_retries_query_cb(const struct ofono_error *error,
int retries[OFONO_SIM_PASSWORD_INVALID],
void *data)
@@ -773,36 +683,6 @@ static gboolean sim_allow(DBusMessage *msg,
OFONO_DBUS_ACCESS_INTF_SIMMGR, method, arg);
}
static void sim_set_slot_callback(const struct ofono_error *error, void *data)
{
struct ofono_sim *sim = data;
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(sim->atom);
DBusMessage *reply;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Error setting radio access mode");
sim->pending_active_card_slot = sim->active_card_slot;
reply = __ofono_error_from_error(error, sim->pending);
__ofono_dbus_pending_reply(&sim->pending, reply);
return;
}
sim->active_card_slot = sim->pending_active_card_slot;
reply = dbus_message_new_method_return(sim->pending);
__ofono_dbus_pending_reply(&sim->pending, reply);
ofono_dbus_signal_property_changed(conn, path,
OFONO_SIM_MANAGER_INTERFACE,
"ActiveCardSlot",
DBUS_TYPE_UINT32,
&sim->active_card_slot);
}
static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -873,37 +753,6 @@ error:
if (set_ok)
return NULL;
} else if (!strcmp(name, "ActiveCardSlot")) {
dbus_uint32_t value;
dbus_message_iter_next(&iter);
if (sim->driver->set_active_card_slot == NULL)
return __ofono_error_not_implemented(msg);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
dbus_message_iter_recurse(&iter, &var);
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT32)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &value);
if (value <= 0 || value > sim->card_slot_count)
return __ofono_error_invalid_args(msg);
if (sim->active_card_slot == value)
return dbus_message_new_method_return(msg);
sim->pending = dbus_message_ref(msg);
sim->pending_active_card_slot = value;
sim->driver->set_active_card_slot(sim, value - 1,
sim_set_slot_callback,
sim);
return NULL;
}
return __ofono_error_invalid_args(msg);
@@ -936,11 +785,6 @@ static void sim_locked_cb(struct ofono_sim *sim, gboolean locked)
OFONO_SIM_MANAGER_INTERFACE,
"LockedPins", DBUS_TYPE_STRING,
&locked_pins);
/* Cache pin only for SIM PIN type */
if (g_strcmp0(typestr, "pin") == 0)
pin_cache_update(sim->iccid, pin);
g_strfreev(locked_pins);
sim_pin_retries_check(sim);
@@ -1042,14 +886,6 @@ static DBusMessage *sim_unlock_pin(DBusConnection *conn, DBusMessage *msg,
static void sim_change_pin_cb(const struct ofono_error *error, void *data)
{
struct ofono_sim *sim = data;
const char *typestr;
const char *old;
const char *new;
dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr,
DBUS_TYPE_STRING, &old,
DBUS_TYPE_STRING, &new,
DBUS_TYPE_INVALID);
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
__ofono_dbus_pending_reply(&sim->pending,
@@ -1060,10 +896,6 @@ static void sim_change_pin_cb(const struct ofono_error *error, void *data)
return;
}
/* Cache pin only for SIM PIN type */
if (g_strcmp0(typestr, "pin") == 0)
pin_cache_update(sim->iccid, new);
__ofono_dbus_pending_reply(&sim->pending,
dbus_message_new_method_return(sim->pending));
@@ -1118,14 +950,8 @@ static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg,
static void sim_enter_pin_cb(const struct ofono_error *error, void *data)
{
struct ofono_sim *sim = data;
const char *typestr;
const char *pin;
DBusMessage *reply;
dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr,
DBUS_TYPE_STRING, &pin,
DBUS_TYPE_INVALID);
if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
reply = __ofono_error_failed(sim->pending);
else
@@ -1137,10 +963,6 @@ static void sim_enter_pin_cb(const struct ofono_error *error, void *data)
if (sim->initialized || error->type != OFONO_ERROR_TYPE_NO_ERROR)
goto recheck;
/* Cache pin only for SIM PIN type */
if (g_strcmp0(typestr, "pin") == 0)
pin_cache_update(sim->iccid, pin);
if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN ||
sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) {
sim->wait_initialized = true;
@@ -3096,8 +2918,6 @@ void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted)
sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PIN2] = -1;
sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PUK2] = -1;
pin_cache_remove(sim->iccid);
sim_free_state(sim);
}
}
@@ -3371,8 +3191,7 @@ static void sim_pin_query_cb(const struct ofono_error *error,
struct ofono_sim *sim = data;
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(sim->atom);
struct cached_pin *cpins = pin_cache_lookup(sim->iccid);
const char *pin_name = sim_passwd_name(pin_type);
const char *pin_name;
char **locked_pins;
gboolean lock_changed;
@@ -3385,6 +3204,7 @@ static void sim_pin_query_cb(const struct ofono_error *error,
if (sim->pin_type != pin_type) {
sim->pin_type = pin_type;
pin_name = sim_passwd_name(pin_type);
if (pin_type != OFONO_SIM_PASSWORD_NONE &&
password_is_pin(pin_type) == FALSE)
@@ -3415,10 +3235,6 @@ static void sim_pin_query_cb(const struct ofono_error *error,
&pin_name);
}
if (g_strcmp0(pin_name, "pin") == 0 && cpins != NULL)
sim->driver->send_passwd(sim, cpins->pin,
pin_cache_enter_cb, sim);
switch (pin_type) {
case OFONO_SIM_PASSWORD_NONE:
case OFONO_SIM_PASSWORD_SIM_PIN2:
@@ -3463,56 +3279,21 @@ void __ofono_sim_recheck_pin(struct ofono_sim *sim)
int ofono_sim_driver_register(const struct ofono_sim_driver *d)
{
return ofono_sim_driver_register_version(d, 1);
}
int ofono_sim_driver_register_version(const struct ofono_sim_driver *d, int v)
{
struct ofono_sim_driver_data *dd;
DBG("driver: %p, v: %d, name: %s", d, v, d->name);
DBG("driver: %p, name: %s", d, d->name);
if (d->probe == NULL)
return -EINVAL;
/* Pad struct ofono_sim_driver with zeros if necessary */
dd = g_new0(struct ofono_sim_driver_data, 1);
dd->d = d;
switch (v) {
case 0:
memcpy(dd, d, G_STRUCT_OFFSET(struct ofono_sim_driver,
open_channel2));
break;
case 1:
memcpy(dd, d, G_STRUCT_OFFSET(struct ofono_sim_driver,
set_active_card_slot));
break;
default:
memcpy(dd, d, sizeof(*d));
break;
}
g_drivers = g_slist_prepend(g_drivers, dd);
g_drivers = g_slist_prepend(g_drivers, (void *) d);
return 0;
}
void ofono_sim_driver_unregister(const struct ofono_sim_driver *d)
{
GSList *l;
DBG("driver: %p, name: %s", d, d->name);
for (l = g_drivers; l; l = l->next) {
struct ofono_sim_driver_data *dd = l->data;
if (dd->d == d) {
g_drivers = g_slist_delete_link(g_drivers, l);
g_free(dd);
break;
}
}
g_drivers = g_slist_remove(g_drivers, (void *) d);
}
static void emulator_remove_handler(struct ofono_atom *atom, void *data)
@@ -3596,9 +3377,6 @@ struct ofono_sim *ofono_sim_create(struct ofono_modem *modem,
for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
sim->pin_retries[i] = -1;
sim->active_card_slot = 1;
sim->card_slot_count = 1;
for (l = g_drivers; l; l = l->next) {
const struct ofono_sim_driver *drv = l->data;
@@ -3697,14 +3475,6 @@ void ofono_sim_register(struct ofono_sim *sim)
__ofono_atom_register(sim->atom, sim_unregister);
}
void __ofono_sim_clear_cached_pins(struct ofono_sim *sim)
{
if (cached_pins == NULL)
return;
pin_cache_remove(sim->iccid);
}
void ofono_sim_remove(struct ofono_sim *sim)
{
__ofono_atom_free(sim->atom);
@@ -4120,15 +3890,3 @@ int ofono_sim_logical_access(struct ofono_sim *sim, int session_id,
return 0;
}
void ofono_sim_set_card_slot_count(struct ofono_sim *sim, unsigned int val)
{
if (sim)
sim->card_slot_count = val;
}
void ofono_sim_set_active_card_slot(struct ofono_sim *sim, unsigned int val)
{
if (sim)
sim->active_card_slot = val;
}

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

@@ -4,8 +4,7 @@ import sys
import dbus
if (len(sys.argv) < 2):
print("Usage: %s [modem] <number> [enabled|disabled|default]" % (sys.argv[0]))
print("Last argument enables/disables callerid")
print("Usage: %s [modem] <number> [hide_callerid]" % (sys.argv[0]))
sys.exit(1)
bus = dbus.SystemBus()

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
Name: ofono
Summary: Open Source Telephony
Version: 1.29
Version: 1.28
Release: 1
License: GPLv2
URL: https://github.com/sailfishos/ofono