mirror of
https://github.com/sailfishos/ofono
synced 2025-11-26 04:11:05 +08:00
Compare commits
88 Commits
mer/1.28+g
...
1.29+git10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7227c6cad | ||
|
|
cff7c7adb1 | ||
|
|
a50522b062 | ||
|
|
bb7d65f41a | ||
|
|
278f28d15c | ||
|
|
3afa0876c6 | ||
|
|
04162f719e | ||
|
|
4ae4d688ce | ||
|
|
224b551feb | ||
|
|
6acf808d89 | ||
|
|
942b2efc3b | ||
|
|
301b880a87 | ||
|
|
933525829f | ||
|
|
d8df18c80c | ||
|
|
47fd559c1b | ||
|
|
8fa9a7068f | ||
|
|
10c1d7ac75 | ||
|
|
81ad45dfd9 | ||
|
|
0e27cf811b | ||
|
|
5ec5081b7d | ||
|
|
d2cae30a03 | ||
|
|
e0ea7b54c6 | ||
|
|
01c5e7fc1a | ||
|
|
291530d291 | ||
|
|
108611ef72 | ||
|
|
a3c9fc793c | ||
|
|
03491c78e7 | ||
|
|
c534b7e9b0 | ||
|
|
35e7cd19e6 | ||
|
|
2ed8b1bb7f | ||
|
|
8f65b01f4c | ||
|
|
1aa2ac5e67 | ||
|
|
cb8a13433f | ||
|
|
ee1c34cd7f | ||
|
|
2b89f6d488 | ||
|
|
32b886d89d | ||
|
|
a9a3e024e1 | ||
|
|
8c432e5426 | ||
|
|
fc26876503 | ||
|
|
7461d52b10 | ||
|
|
9e2fd992b5 | ||
|
|
1295539515 | ||
|
|
65aa5aab14 | ||
|
|
8da2178a96 | ||
|
|
181c74b1a9 | ||
|
|
a30ef13844 | ||
|
|
ec85e50ab4 | ||
|
|
1cedb9d750 | ||
|
|
a412839f45 | ||
|
|
86af7cd7c9 | ||
|
|
050332577c | ||
|
|
339814e429 | ||
|
|
278d7236c9 | ||
|
|
15a9ea2977 | ||
|
|
9910ab1693 | ||
|
|
d5a3613fd4 | ||
|
|
d337893b39 | ||
|
|
9ef41fdc2f | ||
|
|
c779a8b19d | ||
|
|
81c7f886cb | ||
|
|
4adac31b51 | ||
|
|
31bebd7ecf | ||
|
|
f1965b1e2b | ||
|
|
fed8c5b171 | ||
|
|
5e1f159ad1 | ||
|
|
972aea87e8 | ||
|
|
f4df805783 | ||
|
|
1066668a4b | ||
|
|
c5029eafcf | ||
|
|
6ce1e081a4 | ||
|
|
91435c39ed | ||
|
|
531afae6b2 | ||
|
|
1c8a577a4b | ||
|
|
bd175869f4 | ||
|
|
bcb08afc50 | ||
|
|
eb8bfb57e9 | ||
|
|
871eab499c | ||
|
|
dae12e74a4 | ||
|
|
9f486aa91a | ||
|
|
b015849e98 | ||
|
|
6c77fa2ddd | ||
|
|
09bd3cc5ac | ||
|
|
1758eb3b2a | ||
|
|
faae02c2f4 | ||
|
|
d2abaa7776 | ||
|
|
78e83f877c | ||
|
|
2b00591782 | ||
|
|
18b38db35f |
@@ -1,3 +1,9 @@
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT(ofono, 1.28)
|
||||
AC_INIT(ofono, 1.29)
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@@ -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".
|
||||
|
||||
@@ -205,3 +205,15 @@ 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.
|
||||
|
||||
@@ -455,7 +455,6 @@ 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,
|
||||
|
||||
@@ -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,8 +1655,11 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
|
||||
DBG("");
|
||||
|
||||
switch (nd->vendor) {
|
||||
case OFONO_VENDOR_UBLOX_TOBY_L2:
|
||||
/* UBX-13002752 R33: TOBY L2 doesn't support mode 2 and 3 */
|
||||
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.
|
||||
*/
|
||||
mode = "1";
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -75,6 +75,7 @@ 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,
|
||||
@@ -1160,6 +1161,7 @@ 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)
|
||||
@@ -1221,7 +1223,6 @@ 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;
|
||||
@@ -1921,6 +1922,83 @@ 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)
|
||||
{
|
||||
@@ -1939,6 +2017,10 @@ 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;
|
||||
@@ -1958,6 +2040,46 @@ 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,
|
||||
@@ -1983,7 +2105,8 @@ 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
|
||||
.logical_access = at_logical_access,
|
||||
.set_active_card_slot = at_set_active_card_slot
|
||||
};
|
||||
|
||||
static const struct ofono_sim_driver driver_noef = {
|
||||
|
||||
@@ -46,7 +46,6 @@ enum ofono_vendor {
|
||||
OFONO_VENDOR_QUECTEL,
|
||||
OFONO_VENDOR_QUECTEL_M95,
|
||||
OFONO_VENDOR_UBLOX,
|
||||
OFONO_VENDOR_UBLOX_TOBY_L2,
|
||||
OFONO_VENDOR_XMM,
|
||||
OFONO_VENDOR_GEMALTO,
|
||||
};
|
||||
|
||||
@@ -260,6 +260,45 @@ 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;
|
||||
@@ -269,8 +308,11 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
|
||||
const char *laddrnetmask = NULL;
|
||||
const char *gw = NULL;
|
||||
const char *interface;
|
||||
const char *dns[3];
|
||||
const char *ctrlpath;
|
||||
const char *datapath;
|
||||
char buf[512];
|
||||
const char *interface;
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
@@ -327,9 +369,10 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
DBG("DNS2: %s\n", gcd->dns2);
|
||||
DBG("Gateway: %s\n", gcd->gateway);
|
||||
|
||||
interface = ofono_modem_get_string(modem, "NetworkInterface");
|
||||
ctrlpath = ofono_modem_get_string(modem, "CtrlPath");
|
||||
interface = ofono_gprs_context_get_interface(gc);
|
||||
datapath = get_datapath(modem, interface);
|
||||
|
||||
ofono_gprs_context_set_interface(gc, interface);
|
||||
ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE);
|
||||
|
||||
if (gcd->netmask[0])
|
||||
@@ -340,7 +383,17 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
|
||||
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);
|
||||
}
|
||||
|
||||
static void ifx_read_settings(struct ofono_gprs_context *gc)
|
||||
|
||||
@@ -250,6 +250,7 @@ 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:
|
||||
|
||||
@@ -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_result(
|
||||
static enum get_card_status_result handle_get_card_status_data(
|
||||
struct qmi_result *result, struct sim_status *sim_stat)
|
||||
{
|
||||
const void *ptr;
|
||||
@@ -533,9 +533,6 @@ static enum get_card_status_result handle_get_card_status_result(
|
||||
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;
|
||||
@@ -578,6 +575,15 @@ 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;
|
||||
@@ -789,6 +795,34 @@ 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;
|
||||
@@ -810,6 +844,9 @@ 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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -43,12 +43,20 @@
|
||||
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)
|
||||
@@ -227,6 +235,14 @@ 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);
|
||||
}
|
||||
@@ -461,8 +477,44 @@ 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 vendor, void *data)
|
||||
unsigned int model_id, void *data)
|
||||
{
|
||||
GAtChat *chat = data;
|
||||
struct gprs_context_data *gcd;
|
||||
@@ -473,10 +525,23 @@ 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;
|
||||
|
||||
@@ -39,24 +39,85 @@
|
||||
|
||||
#include "ubloxmodem.h"
|
||||
|
||||
static const char *ucgdflt_prefix[] = { "+UCGDFLT:", NULL };
|
||||
static const char *none_prefix[] = { NULL };
|
||||
|
||||
struct lte_driver_data {
|
||||
GAtChat *chat;
|
||||
const struct ublox_model *model;
|
||||
struct ofono_lte_default_attach_info pending_info;
|
||||
};
|
||||
|
||||
static void ucgdflt_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
static void at_lte_set_auth_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)
|
||||
@@ -67,17 +128,32 @@ static void ublox_lte_set_default_attach_info(const struct ofono_lte *lte,
|
||||
|
||||
DBG("LTE config with APN: %s", info->apn);
|
||||
|
||||
if (strlen(info->apn) > 0)
|
||||
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,\"IP\",\"%s\"",
|
||||
info->apn);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "AT+UCGDFLT=0");
|
||||
cbd->user = ldd;
|
||||
memcpy(&ldd->pending_info, info, sizeof(ldd->pending_info));
|
||||
|
||||
/* 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)
|
||||
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),
|
||||
info->apn);
|
||||
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)
|
||||
return;
|
||||
|
||||
cb_data_unref(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
@@ -91,7 +167,7 @@ static gboolean lte_delayed_register(gpointer user_data)
|
||||
}
|
||||
|
||||
static int ublox_lte_probe(struct ofono_lte *lte,
|
||||
unsigned int vendor, void *data)
|
||||
unsigned int model_id, void *data)
|
||||
{
|
||||
GAtChat *chat = data;
|
||||
struct lte_driver_data *ldd;
|
||||
@@ -103,6 +179,7 @@ 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);
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gatchat.h>
|
||||
|
||||
@@ -33,6 +35,83 @@
|
||||
|
||||
#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();
|
||||
|
||||
@@ -23,6 +23,23 @@
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@@ -23,14 +23,17 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <ofono/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum ofono_cell_type {
|
||||
OFONO_CELL_TYPE_GSM,
|
||||
OFONO_CELL_TYPE_WCDMA,
|
||||
OFONO_CELL_TYPE_LTE
|
||||
OFONO_CELL_TYPE_LTE,
|
||||
OFONO_CELL_TYPE_NR /* Since 1.29+git8 */
|
||||
};
|
||||
|
||||
#define OFONO_CELL_INVALID_VALUE (INT_MAX)
|
||||
#define OFONO_CELL_INVALID_VALUE_INT64 (INT64_MAX)
|
||||
|
||||
struct ofono_cell_info_gsm {
|
||||
int mcc; /* Mobile Country Code (0..999) */
|
||||
@@ -70,6 +73,22 @@ struct ofono_cell_info_lte {
|
||||
int timingAdvance; /* (Distance = 300m/us) TS 36.321 */
|
||||
};
|
||||
|
||||
/* Since 1.29+git8 */
|
||||
struct ofono_cell_info_nr {
|
||||
int mcc; /* Mobile Country Code (0..999) */
|
||||
int mnc; /* Mobile Network Code (0..999) */
|
||||
int64_t nci; /* NR Cell Identity */
|
||||
int pci; /* Physical cell id (0..1007) */
|
||||
int tac; /* Tracking area code */
|
||||
int nrarfcn; /* 22-bit NR Absolute RC Channel Number */
|
||||
int ssRsrp; /* SS Reference Signal Receive Power TS 38.215 */
|
||||
int ssRsrq; /* SS Reference Signal Receive Quality TS 38.215 and 38.133 */
|
||||
int ssSinr; /* SS Reference Signal-to-Noise Ratio TS 38.215 and 38.133*/
|
||||
int csiRsrp; /* CSI Reference Signal Receive Power TS 38.215 */
|
||||
int csiRsrq; /* CSI Reference Signal Receive Quality TS 38.215 */
|
||||
int csiSinr; /* CSI Reference Signal-to-Noise Ratio TS 38.215 and 38.133 */
|
||||
};
|
||||
|
||||
typedef struct ofono_cell {
|
||||
enum ofono_cell_type type;
|
||||
ofono_bool_t registered;
|
||||
@@ -77,6 +96,7 @@ typedef struct ofono_cell {
|
||||
struct ofono_cell_info_gsm gsm;
|
||||
struct ofono_cell_info_wcdma wcdma;
|
||||
struct ofono_cell_info_lte lte;
|
||||
struct ofono_cell_info_nr nr; /* Since 1.29+git8 */
|
||||
} info;
|
||||
} *ofono_cell_ptr;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2019-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2022 Jolla Ltd.
|
||||
* Copyright (C) 2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -41,6 +41,8 @@ enum ofono_dbus_access_intf {
|
||||
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS, /* org.ofono.RadioSettings */
|
||||
OFONO_DBUS_ACCESS_INTF_STK, /* org.ofono.SimToolkit */
|
||||
OFONO_DBUS_ACCESS_INTF_OEMRAW, /* org.ofono.OemRaw */
|
||||
/* Since 1.29+git3 */
|
||||
OFONO_DBUS_ACCESS_INTF_IMS, /* org.ofono.IpMultimediaSystem */
|
||||
OFONO_DBUS_ACCESS_INTF_COUNT
|
||||
};
|
||||
|
||||
@@ -53,6 +55,7 @@ enum ofono_dbus_access_message_method {
|
||||
/* OFONO_DBUS_ACCESS_INTF_MESSAGEMGR */
|
||||
enum ofono_dbus_access_messagemgr_method {
|
||||
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE,
|
||||
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE, /* Since 1.28+git5 */
|
||||
OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT
|
||||
};
|
||||
|
||||
@@ -131,6 +134,15 @@ enum ofono_dbus_access_oemraw_method {
|
||||
OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT
|
||||
};
|
||||
|
||||
/* OFONO_DBUS_ACCESS_INTF_IMS */
|
||||
enum ofono_dbus_access_ims_method {
|
||||
/* Since 1.29+git3 */
|
||||
OFONO_DBUS_ACCESS_IMS_SET_PROPERTY,
|
||||
OFONO_DBUS_ACCESS_IMS_REGISTER,
|
||||
OFONO_DBUS_ACCESS_IMS_UNREGISTER,
|
||||
OFONO_DBUS_ACCESS_IMS_METHOD_COUNT
|
||||
};
|
||||
|
||||
#define OFONO_DBUS_ACCESS_PRIORITY_LOW (-100)
|
||||
#define OFONO_DBUS_ACCESS_PRIORITY_DEFAULT (0)
|
||||
#define OFONO_DBUS_ACCESS_PRIORITY_HIGH (100)
|
||||
@@ -158,7 +170,7 @@ const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf);
|
||||
const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
|
||||
int method);
|
||||
|
||||
/* Since mer/1.24+git2 */
|
||||
/* Since 1.24+git2 */
|
||||
ofono_bool_t ofono_dbus_access_method_allowed(const char *sender,
|
||||
enum ofono_dbus_access_intf iface, int method, const char *arg);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Telephony stack for Linux
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -65,6 +66,9 @@ void *ofono_devinfo_get_data(struct ofono_devinfo *info);
|
||||
|
||||
struct ofono_modem *ofono_devinfo_get_modem(struct ofono_devinfo *info);
|
||||
|
||||
/* Since 1.28+git4 */
|
||||
const char *ofono_devinfo_get_serial(struct ofono_devinfo *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -93,6 +93,8 @@ 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);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -30,6 +31,10 @@ extern "C" {
|
||||
|
||||
struct ofono_ims;
|
||||
|
||||
/* ext_info bits */
|
||||
#define OFONO_IMS_VOICE_CAPABLE 0x1
|
||||
#define OFONO_IMS_SMS_CAPABLE 0x4
|
||||
|
||||
typedef void (*ofono_ims_register_cb_t)(const struct ofono_error *error,
|
||||
void *data);
|
||||
typedef void (*ofono_ims_status_cb_t)(const struct ofono_error *error,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -29,6 +29,7 @@ extern "C" {
|
||||
|
||||
#include <ofono/types.h>
|
||||
|
||||
struct ofono_devinfo;
|
||||
struct ofono_modem;
|
||||
struct ofono_gprs;
|
||||
struct ofono_sim;
|
||||
@@ -92,7 +93,9 @@ struct ofono_gprs *ofono_modem_get_gprs(struct ofono_modem *modem);
|
||||
struct ofono_voicecall *ofono_modem_get_voicecall(struct ofono_modem *modem);
|
||||
struct ofono_netreg *ofono_modem_get_netreg(struct ofono_modem *modem);
|
||||
struct ofono_radio_settings *ofono_modem_get_radio_settings
|
||||
(struct ofono_modem *modem); /* Since mer/1.24+git2 */
|
||||
(struct ofono_modem *modem); /* Since 1.24+git2 */
|
||||
struct ofono_devinfo *ofono_modem_get_devinfo
|
||||
(struct ofono_modem *modem); /* Since 1.28+git4 */
|
||||
|
||||
void ofono_modem_set_data(struct ofono_modem *modem, void *data);
|
||||
void *ofono_modem_get_data(struct ofono_modem *modem);
|
||||
|
||||
@@ -34,6 +34,7 @@ enum ofono_radio_access_mode {
|
||||
OFONO_RADIO_ACCESS_MODE_GSM = 0x1,
|
||||
OFONO_RADIO_ACCESS_MODE_UMTS = 0x2,
|
||||
OFONO_RADIO_ACCESS_MODE_LTE = 0x4,
|
||||
OFONO_RADIO_ACCESS_MODE_NR = 0x8, /* Since 1.29+git8 */
|
||||
};
|
||||
|
||||
enum ofono_radio_band_gsm {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -138,6 +138,10 @@ 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);
|
||||
@@ -211,15 +215,23 @@ 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);
|
||||
/* Since mer/1.23+git28 */
|
||||
/* API version 1 (since 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);
|
||||
@@ -229,6 +241,9 @@ 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);
|
||||
@@ -241,8 +256,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 mer/1.24+git2 */
|
||||
enum ofono_sim_password_type ofono_sim_puk2pin( /* Since mer/1.24+git2 */
|
||||
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 */
|
||||
enum ofono_sim_password_type type);
|
||||
|
||||
unsigned int ofono_sim_add_state_watch(struct ofono_sim *sim,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -60,6 +61,11 @@ struct ofono_sms_driver {
|
||||
ofono_sms_bearer_set_cb_t, void *data);
|
||||
};
|
||||
|
||||
enum ofono_sms_data_flag {
|
||||
OFONO_SMS_DATA_FLAG_DELIVERY_REPORT = 0x01,
|
||||
OFONO_SMS_DATA_FLAG_USE_LITTLE_ENDIAN = 0x02
|
||||
}; /* Since 1.28+git5 */
|
||||
|
||||
void ofono_sms_deliver_notify(struct ofono_sms *sms, const unsigned char *pdu,
|
||||
int len, int tpdu_len);
|
||||
void ofono_sms_status_notify(struct ofono_sms *sms, const unsigned char *pdu,
|
||||
|
||||
@@ -55,7 +55,13 @@ 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_EUTRAN = 7,
|
||||
OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 = 8,
|
||||
OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 = 9,
|
||||
OFONO_ACCESS_TECHNOLOGY_EUTRA_5GCN = 10, /* Since 1.29+git8 */
|
||||
OFONO_ACCESS_TECHNOLOGY_NR_5GCN = 11, /* Since 1.29+git8 */
|
||||
OFONO_ACCESS_TECHNOLOGY_NG_RAN = 12, /* Since 1.29+git8 */
|
||||
OFONO_ACCESS_TECHNOLOGY_EUTRA_NR = 13, /* Since 1.29+git8 */
|
||||
};
|
||||
|
||||
/* 27.007 Section 6.2 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2018-2022 Jolla Ltd. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -52,6 +53,11 @@ typedef struct GAtResult GAtResult;
|
||||
|
||||
#define HFP_AG_DRIVER "hfp-ag-driver"
|
||||
|
||||
struct watch_fd {
|
||||
guint id;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static gboolean hfp_ag_enabled;
|
||||
static guint service_watch_id;
|
||||
static guint modemwatch_id;
|
||||
@@ -145,11 +151,12 @@ static struct ofono_handsfree_card_driver hfp_ag_driver = {
|
||||
|
||||
static void connection_destroy(gpointer data)
|
||||
{
|
||||
int fd = GPOINTER_TO_INT(data);
|
||||
struct watch_fd *watch = data;
|
||||
|
||||
DBG("fd %d", fd);
|
||||
DBG("fd %d", watch->fd);
|
||||
|
||||
close(fd);
|
||||
g_source_remove(watch->id);
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
static gboolean io_hup_cb(GIOChannel *io, GIOCondition cond, gpointer data)
|
||||
@@ -169,7 +176,8 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
|
||||
DBusMessageIter entry;
|
||||
const char *device;
|
||||
GIOChannel *io;
|
||||
int fd, fd_dup;
|
||||
int fd;
|
||||
struct watch_fd *watch;
|
||||
struct sockaddr_rc saddr;
|
||||
socklen_t optlen;
|
||||
struct ofono_emulator *em;
|
||||
@@ -252,10 +260,12 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
|
||||
emulator = em;
|
||||
ofono_emulator_register(em, fd);
|
||||
|
||||
fd_dup = dup(fd);
|
||||
io = g_io_channel_unix_new(fd_dup);
|
||||
g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_HUP, io_hup_cb,
|
||||
g_strdup(device), g_free);
|
||||
watch = g_new(struct watch_fd, 1);
|
||||
watch->fd = dup(fd);
|
||||
io = g_io_channel_unix_new(watch->fd);
|
||||
g_io_channel_set_close_on_unref(io, TRUE);
|
||||
watch->id = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_HUP,
|
||||
io_hup_cb, g_strdup(device), g_free);
|
||||
g_io_channel_unref(io);
|
||||
|
||||
card = ofono_handsfree_card_create(0,
|
||||
@@ -269,8 +279,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
|
||||
|
||||
ofono_emulator_set_handsfree_card(em, card);
|
||||
|
||||
g_hash_table_insert(connection_hash, g_strdup(device),
|
||||
GINT_TO_POINTER(fd_dup));
|
||||
g_hash_table_insert(connection_hash, g_strdup(device), watch);
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
@@ -304,7 +313,7 @@ static DBusMessage *profile_disconnection(DBusConnection *conn,
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
const char *device;
|
||||
gpointer fd;
|
||||
struct watch_fd *watch;
|
||||
|
||||
DBG("Profile handler RequestDisconnection");
|
||||
|
||||
@@ -318,11 +327,11 @@ static DBusMessage *profile_disconnection(DBusConnection *conn,
|
||||
|
||||
DBG("%s", device);
|
||||
|
||||
fd = g_hash_table_lookup(connection_hash, device);
|
||||
if (fd == NULL)
|
||||
watch = g_hash_table_lookup(connection_hash, device);
|
||||
if (watch == NULL)
|
||||
goto invalid;
|
||||
|
||||
shutdown(GPOINTER_TO_INT(fd), SHUT_RDWR);
|
||||
shutdown(watch->fd, SHUT_RDWR);
|
||||
|
||||
g_hash_table_remove(connection_hash, device);
|
||||
|
||||
|
||||
@@ -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 = SIM800;
|
||||
data->modem_type = SIM900;
|
||||
else
|
||||
data->modem_type = SIMCOM_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -42,23 +42,24 @@
|
||||
#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 supported_models {
|
||||
SARA_G270 = 1102,
|
||||
TOBYL2_COMPATIBLE_MODE = 1141,
|
||||
TOBYL2_MEDIUM_THROUGHPUT_MODE = 1143,
|
||||
TOBYL2_HIGH_THROUGHPUT_MODE = 1146,
|
||||
enum ublox_device_flags {
|
||||
UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE = (1 << 0),
|
||||
};
|
||||
|
||||
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)
|
||||
@@ -144,77 +145,151 @@ 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);
|
||||
|
||||
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.
|
||||
data->aux = open_device(modem, "Aux", "Aux: ");
|
||||
/* If this is a serial modem then the device may be behind
|
||||
* the 'Device' attribute instead...
|
||||
*/
|
||||
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;
|
||||
if (data->aux == NULL) {
|
||||
data->aux = open_device(modem, "Device", "Aux: ");
|
||||
if (data->aux == NULL)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
data->modem = open_device(modem, "Modem", "Modem: ");
|
||||
if (data->modem) {
|
||||
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 +CMEE=1", none_prefix,
|
||||
g_at_chat_send(data->aux, "ATE0", none_prefix,
|
||||
NULL, NULL, NULL);
|
||||
g_at_chat_send(data->aux, "AT+CMEE=1", none_prefix,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix,
|
||||
cfun_enable, modem, NULL);
|
||||
if (g_at_chat_send(data->aux, "AT+CGMM", NULL,
|
||||
query_model_cb, modem, NULL) > 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
return -EINPROGRESS;
|
||||
g_at_chat_unref(data->aux);
|
||||
data->aux = NULL;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
@@ -308,19 +383,34 @@ 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 = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ?
|
||||
"ubloxmodem" : "atmodem";
|
||||
const char *driver;
|
||||
/* Toby L2: Create same number of contexts as supported PDP contexts. */
|
||||
int ncontexts = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ? 8 : 1;
|
||||
int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1;
|
||||
int variant;
|
||||
|
||||
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, data->vendor_family,
|
||||
driver, chat);
|
||||
gc = ofono_gprs_context_create(modem, variant, driver, chat);
|
||||
|
||||
if (gprs && gc)
|
||||
ofono_gprs_add_context(gprs, gc);
|
||||
@@ -328,7 +418,8 @@ static void ublox_post_sim(struct ofono_modem *modem)
|
||||
--ncontexts;
|
||||
}
|
||||
|
||||
ofono_lte_create(modem, 0, "ubloxmodem", data->aux);
|
||||
ofono_lte_create(modem,
|
||||
ublox_model_to_id(data->model), "ubloxmodem", data->aux);
|
||||
}
|
||||
|
||||
static void ublox_post_online(struct ofono_modem *modem)
|
||||
|
||||
@@ -1090,11 +1090,17 @@ 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(info->number, "02") == 0)
|
||||
aux = info->devnode;
|
||||
else if (g_strcmp0(info->number, "00") == 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)
|
||||
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;
|
||||
@@ -1111,7 +1117,6 @@ 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;
|
||||
@@ -1179,7 +1184,7 @@ static gboolean setup_gemalto(struct modem_info* modem)
|
||||
|
||||
static gboolean setup_xmm7xxx(struct modem_info *modem)
|
||||
{
|
||||
const char *mdm = NULL, *net = NULL;
|
||||
const char *mdm = NULL, *net = NULL, *net2 = NULL, *net3 = NULL;
|
||||
GSList *list;
|
||||
|
||||
DBG("%s %s %s %s %s %s\n", modem->syspath, modem->devname,
|
||||
@@ -1199,6 +1204,10 @@ 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) {
|
||||
@@ -1219,6 +1228,15 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1678,6 +1696,8 @@ 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" },
|
||||
|
||||
@@ -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_IFX, "atmodem",
|
||||
data->sim = ofono_sim_create(modem, OFONO_VENDOR_XMM, "atmodem",
|
||||
data->chat);
|
||||
}
|
||||
|
||||
@@ -1269,6 +1269,7 @@ 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);
|
||||
|
||||
@@ -1276,11 +1277,39 @@ 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);
|
||||
|
||||
@@ -771,7 +771,7 @@ static void sim_cbmi_read_cb(int ok, int length, int record,
|
||||
|
||||
mi = (data[i] << 8) + data[i+1];
|
||||
|
||||
if (mi > 999)
|
||||
if (mi > CBS_MAX_TOPIC)
|
||||
continue;
|
||||
|
||||
range = g_new0(struct cbs_topic_range, 1);
|
||||
@@ -818,7 +818,7 @@ static void sim_cbmir_read_cb(int ok, int length, int record,
|
||||
min = (data[i] << 8) + data[i+1];
|
||||
max = (data[i+2] << 8) + data[i+3];
|
||||
|
||||
if (min > 999 || max > 999 || min > max)
|
||||
if (min > CBS_MAX_TOPIC || max > CBS_MAX_TOPIC || min > max)
|
||||
continue;
|
||||
|
||||
range = g_new0(struct cbs_topic_range, 1);
|
||||
|
||||
@@ -57,14 +57,19 @@ struct cell_property {
|
||||
const char *name;
|
||||
glong off;
|
||||
int flag;
|
||||
int type;
|
||||
};
|
||||
|
||||
#define CELL_GSM_PROPERTY(value,name) \
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_gsm,name), value }
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_gsm,name), value, DBUS_TYPE_INT32 }
|
||||
#define CELL_WCDMA_PROPERTY(value,name) \
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_wcdma,name), value }
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_wcdma,name), value, DBUS_TYPE_INT32 }
|
||||
#define CELL_LTE_PROPERTY(value,name) \
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_lte,name), value }
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_lte,name), value, DBUS_TYPE_INT32 }
|
||||
#define CELL_NR_PROPERTY(value,name) \
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_nr,name), value, DBUS_TYPE_INT32 }
|
||||
#define CELL_NR_PROPERTY64(value,name) \
|
||||
{ #name, G_STRUCT_OFFSET(struct ofono_cell_info_nr,name), value, DBUS_TYPE_INT64 }
|
||||
|
||||
static const struct cell_property cell_gsm_properties [] = {
|
||||
CELL_GSM_PROPERTY(0x001,mcc),
|
||||
@@ -104,6 +109,21 @@ static const struct cell_property cell_lte_properties [] = {
|
||||
CELL_LTE_PROPERTY(0x800,timingAdvance)
|
||||
};
|
||||
|
||||
static const struct cell_property cell_nr_properties [] = {
|
||||
CELL_NR_PROPERTY(0x001,mcc),
|
||||
CELL_NR_PROPERTY(0x002,mnc),
|
||||
CELL_NR_PROPERTY64(0x004,nci),
|
||||
CELL_NR_PROPERTY(0x008,pci),
|
||||
CELL_NR_PROPERTY(0x010,tac),
|
||||
CELL_NR_PROPERTY(0x020,nrarfcn),
|
||||
CELL_NR_PROPERTY(0x040,ssRsrp),
|
||||
CELL_NR_PROPERTY(0x080,ssRsrq),
|
||||
CELL_NR_PROPERTY(0x100,ssSinr),
|
||||
CELL_NR_PROPERTY(0x200,csiRsrp),
|
||||
CELL_NR_PROPERTY(0x400,csiRsrq),
|
||||
CELL_NR_PROPERTY(0x800,csiSinr),
|
||||
};
|
||||
|
||||
#define CELL_PROPERTY_REGISTERED 0x1000
|
||||
|
||||
typedef void (*cell_info_dbus_append_fn)(DBusMessageIter *it,
|
||||
@@ -124,6 +144,8 @@ static const char *cell_info_dbus_cell_type_str(enum ofono_cell_type type)
|
||||
return "wcdma";
|
||||
case OFONO_CELL_TYPE_LTE:
|
||||
return "lte";
|
||||
case OFONO_CELL_TYPE_NR:
|
||||
return "nr";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@@ -142,6 +164,9 @@ static const struct cell_property *cell_info_dbus_cell_properties
|
||||
case OFONO_CELL_TYPE_LTE:
|
||||
*count = G_N_ELEMENTS(cell_lte_properties);
|
||||
return cell_lte_properties;
|
||||
case OFONO_CELL_TYPE_NR:
|
||||
*count = G_N_ELEMENTS(cell_nr_properties);
|
||||
return cell_nr_properties;
|
||||
default:
|
||||
*count = 0;
|
||||
return NULL;
|
||||
@@ -202,10 +227,18 @@ static void cell_info_dbus_append_properties(DBusMessageIter *it,
|
||||
|
||||
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, "{sv}", &dict);
|
||||
for (i = 0; i < n; i++) {
|
||||
gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
|
||||
if (value != OFONO_CELL_INVALID_VALUE) {
|
||||
ofono_dbus_dict_append(&dict, prop[i].name,
|
||||
DBUS_TYPE_INT32, &value);
|
||||
if (prop[i].type == DBUS_TYPE_INT64) {
|
||||
gint64 value = G_STRUCT_MEMBER(gint64, &cell->info, prop[i].off);
|
||||
if (value != OFONO_CELL_INVALID_VALUE_INT64) {
|
||||
ofono_dbus_dict_append(&dict, prop[i].name,
|
||||
DBUS_TYPE_INT64, &value);
|
||||
}
|
||||
} else {
|
||||
gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
|
||||
if (value != OFONO_CELL_INVALID_VALUE) {
|
||||
ofono_dbus_dict_append(&dict, prop[i].name,
|
||||
DBUS_TYPE_INT32, &value);
|
||||
}
|
||||
}
|
||||
}
|
||||
dbus_message_iter_close_container(it, &dict);
|
||||
@@ -375,11 +408,20 @@ static int cell_info_dbus_compare(const struct ofono_cell *c1,
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
const glong offset = prop[i].off;
|
||||
gint32 v1 = G_STRUCT_MEMBER(int, &c1->info, offset);
|
||||
gint32 v2 = G_STRUCT_MEMBER(int, &c2->info, offset);
|
||||
if (prop[i].type == DBUS_TYPE_INT64) {
|
||||
gint64 v1 = G_STRUCT_MEMBER(gint64, &c1->info, offset);
|
||||
gint64 v2 = G_STRUCT_MEMBER(gint64, &c2->info, offset);
|
||||
|
||||
if (v1 != v2) {
|
||||
mask |= prop[i].flag;
|
||||
if (v1 != v2) {
|
||||
mask |= prop[i].flag;
|
||||
}
|
||||
} else {
|
||||
gint32 v1 = G_STRUCT_MEMBER(int, &c1->info, offset);
|
||||
gint32 v2 = G_STRUCT_MEMBER(int, &c2->info, offset);
|
||||
|
||||
if (v1 != v2) {
|
||||
mask |= prop[i].flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +469,7 @@ static void cell_info_dbus_property_changed(CellInfoDBus *dbus,
|
||||
ofono_dbus_clients_signal_property_changed(
|
||||
dbus->clients, entry->path,
|
||||
CELL_DBUS_INTERFACE, prop[i].name,
|
||||
DBUS_TYPE_INT32,
|
||||
prop[i].type,
|
||||
G_STRUCT_MEMBER_P(&cell->info, prop[i].off));
|
||||
mask &= ~prop[i].flag;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,23 @@ int ofono_cell_compare_location(const struct ofono_cell *c1,
|
||||
} else {
|
||||
return l1->tac - l2->tac;
|
||||
}
|
||||
} else if (c1->type == OFONO_CELL_TYPE_NR) {
|
||||
const struct ofono_cell_info_nr *n1 =
|
||||
&c1->info.nr;
|
||||
const struct ofono_cell_info_nr *n2 =
|
||||
&c2->info.nr;
|
||||
|
||||
if (n1->mcc != n2->mcc) {
|
||||
return n1->mcc - n2->mcc;
|
||||
} else if (n1->mnc != n2->mnc) {
|
||||
return n1->mnc - n2->mnc;
|
||||
} else if (n1->nci != n2->nci) {
|
||||
return n1->nci - n2->nci;
|
||||
} else if (n1->pci != n2->pci) {
|
||||
return n1->pci - n2->pci;
|
||||
} else {
|
||||
return n1->tac - n2->tac;
|
||||
}
|
||||
} else {
|
||||
ofono_warn("Unexpected cell type");
|
||||
return 0;
|
||||
|
||||
@@ -706,8 +706,20 @@ 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 ACCESS_TECHNOLOGY_EUTRA_5GCN:
|
||||
return "lte";
|
||||
case ACCESS_TECHNOLOGY_NR_5GCN:
|
||||
case ACCESS_TECHNOLOGY_NG_RAN:
|
||||
case ACCESS_TECHNOLOGY_EUTRA_NR:
|
||||
return "nr";
|
||||
case OFONO_ACCESS_TECHNOLOGY_NONE:
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -42,6 +42,18 @@
|
||||
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 */
|
||||
#define ACCESS_TECHNOLOGY_EUTRA_5GCN \
|
||||
OFONO_ACCESS_TECHNOLOGY_EUTRA_5GCN /* 10 */
|
||||
#define ACCESS_TECHNOLOGY_NR_5GCN \
|
||||
OFONO_ACCESS_TECHNOLOGY_NR_5GCN /* 11 */
|
||||
#define ACCESS_TECHNOLOGY_NG_RAN \
|
||||
OFONO_ACCESS_TECHNOLOGY_NG_RAN /* 12 */
|
||||
#define ACCESS_TECHNOLOGY_EUTRA_NR \
|
||||
OFONO_ACCESS_TECHNOLOGY_EUTRA_NR /* 13 */
|
||||
|
||||
/* 27.007 Section 7.2 <stat> */
|
||||
#define NETWORK_REGISTRATION_STATUS_NOT_REGISTERED \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -243,6 +243,7 @@ static void conf_merge_group(GKeyFile *conf, GKeyFile *k, const char *group)
|
||||
group, key, &count, NULL);
|
||||
|
||||
key[len-1] = 0;
|
||||
g_strchomp(key); /* Strip spaces before + */
|
||||
conf_list_append(conf, k, group, key,
|
||||
values, count, last == '?');
|
||||
g_strfreev(values);
|
||||
@@ -252,6 +253,7 @@ static void conf_merge_group(GKeyFile *conf, GKeyFile *k, const char *group)
|
||||
group, key, &count, NULL);
|
||||
|
||||
key[len-1] = 0;
|
||||
g_strchomp(key); /* Strip spaces before - */
|
||||
conf_list_remove(conf, k, group, key,
|
||||
values, count);
|
||||
g_strfreev(values);
|
||||
@@ -531,13 +533,16 @@ gboolean ofono_conf_get_mask(GKeyFile *file, const char *group,
|
||||
char **values, **ptr;
|
||||
|
||||
if (comment) *comment = 0;
|
||||
values = g_strsplit(str, "+", -1);
|
||||
values = g_strsplit_set(str, "+,", -1);
|
||||
|
||||
for (ok = TRUE, ptr = values; *ptr && ok; ptr++) {
|
||||
const char* found_str = NULL;
|
||||
const char* s = g_strstrip(*ptr);
|
||||
|
||||
if (!strcasecmp(s, name)) {
|
||||
if (!s[0]) {
|
||||
/* Ignore empty entries */
|
||||
continue;
|
||||
} else if (!strcasecmp(s, name)) {
|
||||
found_str = name;
|
||||
if (result) {
|
||||
*result |= value;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2019-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2022 Jolla Ltd.
|
||||
* Copyright (C) 2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -46,6 +46,8 @@ const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf)
|
||||
return OFONO_STK_INTERFACE;
|
||||
case OFONO_DBUS_ACCESS_INTF_OEMRAW:
|
||||
return "org.ofono.OemRaw";
|
||||
case OFONO_DBUS_ACCESS_INTF_IMS:
|
||||
return OFONO_IMS_INTERFACE;
|
||||
case OFONO_DBUS_ACCESS_INTF_COUNT:
|
||||
break;
|
||||
}
|
||||
@@ -68,6 +70,8 @@ const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
|
||||
switch ((enum ofono_dbus_access_messagemgr_method)method) {
|
||||
case OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE:
|
||||
return "SendMessage";
|
||||
case OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE:
|
||||
return "SendDataMessage";
|
||||
case OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT:
|
||||
break;
|
||||
}
|
||||
@@ -186,6 +190,18 @@ const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OFONO_DBUS_ACCESS_INTF_IMS:
|
||||
switch ((enum ofono_dbus_access_ims_method)method) {
|
||||
case OFONO_DBUS_ACCESS_IMS_SET_PROPERTY:
|
||||
return "SetProperty";
|
||||
case OFONO_DBUS_ACCESS_IMS_REGISTER:
|
||||
return "Register";
|
||||
case OFONO_DBUS_ACCESS_IMS_UNREGISTER:
|
||||
return "Unregister";
|
||||
case OFONO_DBUS_ACCESS_IMS_METHOD_COUNT:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OFONO_DBUS_ACCESS_INTF_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,6 @@ struct ipv6_settings {
|
||||
};
|
||||
|
||||
struct context_settings {
|
||||
char *interface;
|
||||
struct ipv4_settings *ipv4;
|
||||
struct ipv6_settings *ipv6;
|
||||
};
|
||||
@@ -121,6 +120,7 @@ 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,12 +361,10 @@ 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;
|
||||
@@ -391,7 +389,7 @@ static void context_settings_append_ipv4(struct context_settings *settings,
|
||||
goto done;
|
||||
|
||||
ofono_dbus_dict_append(&array, "Interface",
|
||||
DBUS_TYPE_STRING, &settings->interface);
|
||||
DBUS_TYPE_STRING, &interface);
|
||||
|
||||
if (settings->ipv4->proxy)
|
||||
ofono_dbus_dict_append(&array, "Proxy", DBUS_TYPE_STRING,
|
||||
@@ -433,6 +431,7 @@ done:
|
||||
}
|
||||
|
||||
static void context_settings_append_ipv4_dict(struct context_settings *settings,
|
||||
const char *interface,
|
||||
DBusMessageIter *dict)
|
||||
{
|
||||
DBusMessageIter entry;
|
||||
@@ -443,12 +442,13 @@ 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, &entry);
|
||||
context_settings_append_ipv4(settings, interface, &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, &settings->interface);
|
||||
DBUS_TYPE_STRING, &interface);
|
||||
|
||||
if (settings->ipv6->ip)
|
||||
ofono_dbus_dict_append(&array, "Address", DBUS_TYPE_STRING,
|
||||
@@ -503,6 +503,7 @@ done:
|
||||
}
|
||||
|
||||
static void context_settings_append_ipv6_dict(struct context_settings *settings,
|
||||
const char *interface,
|
||||
DBusMessageIter *dict)
|
||||
{
|
||||
DBusMessageIter entry;
|
||||
@@ -513,13 +514,14 @@ 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, &entry);
|
||||
context_settings_append_ipv6(settings, interface, &entry);
|
||||
|
||||
dbus_message_iter_close_container(dict, &entry);
|
||||
}
|
||||
|
||||
static void signal_settings(struct pri_context *ctx, const char *prop,
|
||||
void (*append)(struct context_settings *, DBusMessageIter *))
|
||||
void (*append)(struct context_settings *,
|
||||
const char *, DBusMessageIter *))
|
||||
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
@@ -527,6 +529,7 @@ 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,
|
||||
@@ -538,12 +541,15 @@ 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;
|
||||
else
|
||||
interface = ctx->context_driver->interface;
|
||||
} else {
|
||||
settings = NULL;
|
||||
interface = NULL;
|
||||
}
|
||||
|
||||
append(settings, &iter);
|
||||
append(settings, interface, &iter);
|
||||
g_dbus_send_message(conn, signal);
|
||||
}
|
||||
|
||||
@@ -781,18 +787,16 @@ static void pri_setproxy(const char *interface, const char *proxy)
|
||||
static void pri_reset_context_settings(struct pri_context *ctx)
|
||||
{
|
||||
struct context_settings *settings;
|
||||
char *interface;
|
||||
const 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;
|
||||
|
||||
@@ -809,8 +813,6 @@ 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)
|
||||
@@ -826,10 +828,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(settings->interface, settings->ipv4->ip);
|
||||
pri_set_ipv4_addr(gc->interface, settings->ipv4->ip);
|
||||
|
||||
if (ctx->proxy_host)
|
||||
pri_setproxy(settings->interface, ctx->proxy_host);
|
||||
pri_setproxy(gc->interface, ctx->proxy_host);
|
||||
}
|
||||
|
||||
static gboolean pri_str_changed(const char *val, const char *newval)
|
||||
@@ -1056,6 +1058,7 @@ 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);
|
||||
|
||||
@@ -1092,13 +1095,16 @@ 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;
|
||||
else
|
||||
interface = ctx->context_driver->interface;
|
||||
} else {
|
||||
settings = NULL;
|
||||
interface = NULL;
|
||||
}
|
||||
|
||||
context_settings_append_ipv4_dict(settings, dict);
|
||||
context_settings_append_ipv6_dict(settings, dict);
|
||||
context_settings_append_ipv4_dict(settings, interface, dict);
|
||||
context_settings_append_ipv6_dict(settings, interface, dict);
|
||||
}
|
||||
|
||||
static DBusMessage *pri_get_properties(DBusConnection *conn,
|
||||
@@ -1147,8 +1153,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->settings->interface != NULL) {
|
||||
pri_ifupdown(gc->settings->interface, TRUE);
|
||||
if (gc->interface != NULL) {
|
||||
pri_ifupdown(gc->interface, TRUE);
|
||||
|
||||
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
|
||||
gc->settings->ipv4)
|
||||
@@ -1241,8 +1247,8 @@ static void pri_read_settings_callback(const struct ofono_error *error,
|
||||
|
||||
pri_ctx->active = TRUE;
|
||||
|
||||
if (gc->settings->interface != NULL) {
|
||||
pri_ifupdown(gc->settings->interface, TRUE);
|
||||
if (gc->interface != NULL) {
|
||||
pri_ifupdown(gc->interface, TRUE);
|
||||
|
||||
pri_context_signal_settings(pri_ctx, gc->settings->ipv4 != NULL,
|
||||
gc->settings->ipv6 != NULL);
|
||||
@@ -1810,7 +1816,7 @@ static gboolean context_dbus_unregister(struct pri_context *ctx)
|
||||
|
||||
if (ctx->active == TRUE) {
|
||||
const char *interface =
|
||||
ctx->context_driver->settings->interface;
|
||||
ctx->context_driver->interface;
|
||||
|
||||
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS)
|
||||
pri_set_ipv4_addr(interface, NULL);
|
||||
@@ -3112,6 +3118,11 @@ done:
|
||||
g_free(gc->settings);
|
||||
gc->settings = NULL;
|
||||
}
|
||||
|
||||
if (gc->interface) {
|
||||
g_free(gc->interface);
|
||||
gc->interface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ofono_gprs_add_context(struct ofono_gprs *gprs,
|
||||
@@ -3295,13 +3306,16 @@ 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)
|
||||
{
|
||||
struct context_settings *settings = gc->settings;
|
||||
|
||||
g_free(settings->interface);
|
||||
settings->interface = g_strdup(interface);
|
||||
g_free(gc->interface);
|
||||
gc->interface = g_strdup(interface);
|
||||
}
|
||||
|
||||
void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc,
|
||||
|
||||
477
ofono/src/ims.c
477
ofono/src/ims.c
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -35,9 +36,28 @@
|
||||
#include "ofono.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "storage.h"
|
||||
#include "dbus-queue.h"
|
||||
|
||||
#define VOICE_CAPABLE_FLAG 0x1
|
||||
#define SMS_CAPABLE_FLAG 0x4
|
||||
#define VOICE_CAPABLE_FLAG OFONO_IMS_VOICE_CAPABLE
|
||||
#define SMS_CAPABLE_FLAG OFONO_IMS_SMS_CAPABLE
|
||||
|
||||
#define RECHECK_TIMEOUT_SEC (10)
|
||||
|
||||
enum ims_reg_strategy {
|
||||
IMS_REG_DISABLED,
|
||||
IMS_REG_ENABLED,
|
||||
IMS_REG_AUTO
|
||||
#define IMS_REG_DEFAULT IMS_REG_AUTO
|
||||
};
|
||||
|
||||
enum ims_watch_events {
|
||||
WATCH_EVENT_REG_TECH,
|
||||
WATCH_EVENT_IMSI,
|
||||
WATCH_EVENT_COUNT
|
||||
};
|
||||
|
||||
struct ims_call;
|
||||
|
||||
struct ofono_ims {
|
||||
int reg_info;
|
||||
@@ -45,11 +65,313 @@ struct ofono_ims {
|
||||
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)
|
||||
{
|
||||
@@ -71,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;
|
||||
@@ -87,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);
|
||||
@@ -154,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);
|
||||
|
||||
@@ -169,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,
|
||||
@@ -208,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;
|
||||
}
|
||||
@@ -226,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;
|
||||
}
|
||||
@@ -243,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,
|
||||
@@ -268,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);
|
||||
}
|
||||
|
||||
@@ -290,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;
|
||||
@@ -353,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,
|
||||
@@ -373,12 +776,12 @@ static void registration_init_cb(const struct ofono_error *error,
|
||||
|
||||
void ofono_ims_register(struct ofono_ims *ims)
|
||||
{
|
||||
if (!ims->driver->registration_status) {
|
||||
if (!ims->driver || !ims->driver->registration_status) {
|
||||
ofono_ims_finish_register(ims);
|
||||
return;
|
||||
}
|
||||
|
||||
ims->driver->registration_status(ims, registration_init_cb, ims);
|
||||
ims_call_registration_status(ims, registration_init_cb, ims);
|
||||
}
|
||||
|
||||
void ofono_ims_remove(struct ofono_ims *ims)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1150,6 +1150,9 @@ 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)
|
||||
@@ -2371,7 +2374,7 @@ out:
|
||||
modem->emergency--;
|
||||
}
|
||||
|
||||
/* Since mer/1.25+git2 */
|
||||
/* Since 1.25+git2 */
|
||||
|
||||
unsigned int ofono_modem_add_watch(ofono_modemwatch_cb_t cb, void *user,
|
||||
ofono_destroy_func destroy)
|
||||
@@ -2383,3 +2386,15 @@ ofono_bool_t ofono_modem_remove_watch(unsigned int id)
|
||||
{
|
||||
return __ofono_modemwatch_remove(id);
|
||||
}
|
||||
|
||||
/* Since 1.28+git4 */
|
||||
|
||||
struct ofono_devinfo *ofono_modem_get_devinfo(struct ofono_modem *modem)
|
||||
{
|
||||
return __ofono_atom_find(OFONO_ATOM_TYPE_DEVINFO, modem);
|
||||
}
|
||||
|
||||
const char *ofono_devinfo_get_serial(struct ofono_devinfo *info)
|
||||
{
|
||||
return info ? info->serial : NULL;
|
||||
}
|
||||
|
||||
@@ -428,6 +428,7 @@ 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>
|
||||
|
||||
@@ -575,6 +576,9 @@ enum sms_class;
|
||||
|
||||
typedef void (*sms_send_text_cb_t)(struct ofono_sms *sms,
|
||||
const struct sms_address *addr, const char *text, void *data);
|
||||
typedef void (*sms_send_datagram_cb_t)(struct ofono_sms *sms,
|
||||
const struct sms_address *addr, int dstport, int srcport,
|
||||
unsigned char *bytes, unsigned int len, int flags, void *data);
|
||||
|
||||
typedef void (*sms_dispatch_recv_text_cb_t)
|
||||
(struct ofono_sms *sms, const struct ofono_uuid *uuid,
|
||||
@@ -594,6 +598,11 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
|
||||
const struct sms_address *addr, const char *text,
|
||||
sms_send_text_cb_t sender, ofono_destroy_func destroy,
|
||||
void *data);
|
||||
void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
|
||||
const struct sms_address *addr, int dstport, int srcport,
|
||||
unsigned char *bytes, int len, int flags,
|
||||
sms_send_datagram_cb_t sender, ofono_destroy_func destroy,
|
||||
void *data);
|
||||
|
||||
/* Does g_free(buf) when done */
|
||||
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,
|
||||
|
||||
@@ -65,7 +65,9 @@ struct ofono_radio_settings {
|
||||
enum ofono_radio_access_mode ofono_radio_access_max_mode(
|
||||
enum ofono_radio_access_mode mask)
|
||||
{
|
||||
return (mask & OFONO_RADIO_ACCESS_MODE_LTE) ?
|
||||
return (mask & OFONO_RADIO_ACCESS_MODE_NR) ?
|
||||
OFONO_RADIO_ACCESS_MODE_NR :
|
||||
(mask & OFONO_RADIO_ACCESS_MODE_LTE) ?
|
||||
OFONO_RADIO_ACCESS_MODE_LTE :
|
||||
(mask & OFONO_RADIO_ACCESS_MODE_UMTS) ?
|
||||
OFONO_RADIO_ACCESS_MODE_UMTS :
|
||||
@@ -86,6 +88,8 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m)
|
||||
return "umts";
|
||||
case OFONO_RADIO_ACCESS_MODE_LTE:
|
||||
return "lte";
|
||||
case OFONO_RADIO_ACCESS_MODE_NR:
|
||||
return "nr";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -110,6 +114,9 @@ ofono_bool_t ofono_radio_access_mode_from_string(const char *str,
|
||||
} else if (g_str_equal(str, "lte")) {
|
||||
*mode = OFONO_RADIO_ACCESS_MODE_LTE;
|
||||
return TRUE;
|
||||
} else if (g_str_equal(str, "nr")) {
|
||||
*mode = OFONO_RADIO_ACCESS_MODE_NR;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -438,7 +445,7 @@ static void radio_available_rats_query_callback(const struct ofono_error *error,
|
||||
struct ofono_radio_settings *rs = data;
|
||||
|
||||
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
|
||||
rs->available_rats = available_rats & 0x7;
|
||||
rs->available_rats = available_rats & 0xF;
|
||||
else
|
||||
DBG("Error while querying available rats");
|
||||
|
||||
|
||||
254
ofono/src/sim.c
254
ofono/src/sim.c
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -132,6 +132,10 @@ 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;
|
||||
@@ -144,6 +148,11 @@ struct ofono_sim {
|
||||
bool wait_initialized : 1;
|
||||
};
|
||||
|
||||
struct cached_pin {
|
||||
char *id;
|
||||
char *pin;
|
||||
};
|
||||
|
||||
struct msisdn_set_request {
|
||||
struct ofono_sim *sim;
|
||||
int pending;
|
||||
@@ -175,10 +184,18 @@ 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];
|
||||
@@ -558,6 +575,13 @@ 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);
|
||||
|
||||
@@ -567,6 +591,72 @@ 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)
|
||||
@@ -683,6 +773,36 @@ 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)
|
||||
{
|
||||
@@ -753,6 +873,37 @@ 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);
|
||||
@@ -785,6 +936,11 @@ 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);
|
||||
@@ -886,6 +1042,14 @@ 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,
|
||||
@@ -896,6 +1060,10 @@ 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));
|
||||
|
||||
@@ -950,8 +1118,14 @@ 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
|
||||
@@ -963,6 +1137,10 @@ 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;
|
||||
@@ -2918,6 +3096,8 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -3191,7 +3371,8 @@ 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);
|
||||
const char *pin_name;
|
||||
struct cached_pin *cpins = pin_cache_lookup(sim->iccid);
|
||||
const char *pin_name = sim_passwd_name(pin_type);
|
||||
char **locked_pins;
|
||||
gboolean lock_changed;
|
||||
|
||||
@@ -3204,7 +3385,6 @@ 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)
|
||||
@@ -3235,6 +3415,10 @@ 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:
|
||||
@@ -3279,21 +3463,56 @@ void __ofono_sim_recheck_pin(struct ofono_sim *sim)
|
||||
|
||||
int ofono_sim_driver_register(const struct ofono_sim_driver *d)
|
||||
{
|
||||
DBG("driver: %p, name: %s", d, d->name);
|
||||
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);
|
||||
|
||||
if (d->probe == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
g_drivers = g_slist_prepend(g_drivers, (void *) d);
|
||||
/* 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ofono_sim_driver_unregister(const struct ofono_sim_driver *d)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
DBG("driver: %p, name: %s", d, d->name);
|
||||
|
||||
g_drivers = g_slist_remove(g_drivers, (void *) d);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void emulator_remove_handler(struct ofono_atom *atom, void *data)
|
||||
@@ -3377,6 +3596,9 @@ 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;
|
||||
|
||||
@@ -3475,6 +3697,14 @@ 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);
|
||||
@@ -3890,3 +4120,15 @@ 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;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,19 @@ struct sms_filter_chain_send_text {
|
||||
struct ofono_sms_address addr;
|
||||
};
|
||||
|
||||
struct sms_filter_chain_send_datagram {
|
||||
struct sms_filter_message message;
|
||||
sms_send_datagram_cb_t send;
|
||||
ofono_destroy_func destroy;
|
||||
void *data;
|
||||
int dst_port;
|
||||
int src_port;
|
||||
unsigned char *bytes;
|
||||
unsigned int len;
|
||||
int flags;
|
||||
struct ofono_sms_address addr;
|
||||
};
|
||||
|
||||
struct sms_filter_chain_recv_text {
|
||||
struct sms_filter_message message;
|
||||
sms_dispatch_recv_text_cb_t default_handler;
|
||||
@@ -445,6 +458,140 @@ static struct sms_filter_message *sms_filter_send_text_new
|
||||
return &send_msg->message;
|
||||
}
|
||||
|
||||
/* sms_filter_chain_send_datagram */
|
||||
|
||||
static inline struct sms_filter_chain_send_datagram
|
||||
*sms_filter_chain_send_datagram_cast
|
||||
(struct sms_filter_message *msg)
|
||||
{
|
||||
return CAST(msg, struct sms_filter_chain_send_datagram, message);
|
||||
}
|
||||
|
||||
static gboolean sms_filter_chain_send_datagram_can_process
|
||||
(const struct ofono_sms_filter *filter)
|
||||
{
|
||||
return filter->filter_send_datagram != NULL;
|
||||
}
|
||||
|
||||
static void sms_datagram_set_bytes(
|
||||
struct sms_filter_chain_send_datagram *msg,
|
||||
const unsigned char *bytes, unsigned int len)
|
||||
{
|
||||
msg->bytes = g_malloc0(sizeof(unsigned char) * len);
|
||||
memcpy(msg->bytes, bytes, len);
|
||||
msg->len = len;
|
||||
}
|
||||
|
||||
static void sms_filter_chain_send_datagram_process_cb
|
||||
(enum ofono_sms_filter_result res,
|
||||
const struct ofono_sms_address *addr,
|
||||
int dst_port, int src_port,
|
||||
const unsigned char *bytes,
|
||||
unsigned int len, void *data)
|
||||
{
|
||||
struct sms_filter_chain_send_datagram *msg = data;
|
||||
|
||||
if (res != OFONO_SMS_FILTER_DROP) {
|
||||
/* Update the message */
|
||||
if (&msg->addr != addr) {
|
||||
msg->addr = *addr;
|
||||
}
|
||||
if (msg->bytes != bytes) {
|
||||
g_free(msg->bytes);
|
||||
sms_datagram_set_bytes(msg, bytes, len);
|
||||
}
|
||||
|
||||
msg->dst_port = dst_port;
|
||||
msg->src_port = src_port;
|
||||
}
|
||||
|
||||
sms_filter_message_processed(&msg->message, res);
|
||||
}
|
||||
|
||||
static guint sms_filter_chain_send_datagram_process
|
||||
(const struct ofono_sms_filter *filter,
|
||||
struct sms_filter_message *msg)
|
||||
{
|
||||
struct sms_filter_chain_send_datagram *send_msg =
|
||||
sms_filter_chain_send_datagram_cast(msg);
|
||||
struct sms_filter_chain *chain = msg->chain;
|
||||
|
||||
return filter->filter_send_datagram(chain->modem, &send_msg->addr,
|
||||
send_msg->dst_port, send_msg->src_port,
|
||||
send_msg->bytes, send_msg->len,
|
||||
sms_filter_chain_send_datagram_process_cb,
|
||||
send_msg);
|
||||
}
|
||||
|
||||
static void sms_filter_chain_send_datagram_passthrough
|
||||
(struct sms_filter_message *msg)
|
||||
{
|
||||
struct sms_filter_chain_send_datagram *send_msg =
|
||||
sms_filter_chain_send_datagram_cast(msg);
|
||||
|
||||
if (send_msg->send) {
|
||||
struct sms_filter_chain *chain = msg->chain;
|
||||
struct sms_address addr;
|
||||
|
||||
sms_filter_convert_sms_address_back(&addr, &send_msg->addr);
|
||||
send_msg->send(chain->sms, &addr, send_msg->dst_port,
|
||||
send_msg->src_port, send_msg->bytes,
|
||||
send_msg->len, send_msg->flags,
|
||||
send_msg->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void sms_filter_chain_send_datagram_destroy
|
||||
(struct sms_filter_message *msg)
|
||||
{
|
||||
struct sms_filter_chain_send_datagram *send_msg =
|
||||
sms_filter_chain_send_datagram_cast(msg);
|
||||
|
||||
if (send_msg->destroy) {
|
||||
send_msg->destroy(send_msg->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void sms_filter_chain_send_datagram_free
|
||||
(struct sms_filter_message *msg)
|
||||
{
|
||||
struct sms_filter_chain_send_datagram *send_msg =
|
||||
sms_filter_chain_send_datagram_cast(msg);
|
||||
|
||||
g_free(send_msg->bytes);
|
||||
g_free(send_msg);
|
||||
}
|
||||
|
||||
static struct sms_filter_message *sms_filter_send_datagram_new
|
||||
(struct sms_filter_chain *chain, const struct sms_address *addr,
|
||||
int dst_port, int src_port, unsigned char *bytes,
|
||||
unsigned int len, int flags, sms_send_datagram_cb_t send,
|
||||
void *data, ofono_destroy_func destroy)
|
||||
{
|
||||
static const struct sms_filter_message_fn send_datagram_fn = {
|
||||
.name = "outgoing SMS data message",
|
||||
.can_process = sms_filter_chain_send_datagram_can_process,
|
||||
.process = sms_filter_chain_send_datagram_process,
|
||||
.passthrough = sms_filter_chain_send_datagram_passthrough,
|
||||
.destroy = sms_filter_chain_send_datagram_destroy,
|
||||
.free = sms_filter_chain_send_datagram_free
|
||||
};
|
||||
|
||||
struct sms_filter_chain_send_datagram *send_msg =
|
||||
g_new0(struct sms_filter_chain_send_datagram, 1);
|
||||
|
||||
sms_filter_message_init(&send_msg->message, chain, &send_datagram_fn);
|
||||
sms_filter_convert_sms_address(&send_msg->addr, addr);
|
||||
send_msg->send = send;
|
||||
send_msg->destroy = destroy;
|
||||
send_msg->data = data;
|
||||
sms_datagram_set_bytes(send_msg, bytes, len);
|
||||
send_msg->dst_port = dst_port;
|
||||
send_msg->src_port = src_port;
|
||||
send_msg->flags = flags;
|
||||
return &send_msg->message;
|
||||
}
|
||||
|
||||
/* sms_filter_chain_recv_text */
|
||||
|
||||
static inline struct sms_filter_chain_recv_text *
|
||||
@@ -711,6 +858,30 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
|
||||
}
|
||||
}
|
||||
|
||||
void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
|
||||
const struct sms_address *addr, int dstport,
|
||||
int srcport, unsigned char *bytes, int len,
|
||||
int flags, sms_send_datagram_cb_t sender,
|
||||
ofono_destroy_func destroy, void *data)
|
||||
{
|
||||
if (chain) {
|
||||
if (sms_filter_list) {
|
||||
sms_filter_message_process
|
||||
(sms_filter_send_datagram_new(chain, addr,
|
||||
dstport, srcport, bytes, len,
|
||||
flags, sender, data, destroy));
|
||||
return;
|
||||
}
|
||||
if (sender) {
|
||||
sender(chain->sms, addr, dstport, srcport, bytes, len,
|
||||
flags, data);
|
||||
}
|
||||
}
|
||||
if (destroy) {
|
||||
destroy(data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Does g_free(buf) when done */
|
||||
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,
|
||||
const struct ofono_uuid *uuid, int dst_port, int src_port,
|
||||
|
||||
112
ofono/src/sms.c
112
ofono/src/sms.c
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2015-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1043,6 +1043,64 @@ static void sms_send_message_submit(struct ofono_sms *sms,
|
||||
message->pending = NULL;
|
||||
}
|
||||
|
||||
static void sms_send_data_message_submit(struct ofono_sms *sms,
|
||||
const struct sms_address *addr, int dstport,
|
||||
int srcport, unsigned char *bytes, unsigned int len,
|
||||
int flags, void *data)
|
||||
{
|
||||
struct sms_message_data *message = data;
|
||||
const char *to = sms_address_to_string(addr);
|
||||
GSList *msg_list = NULL;
|
||||
gboolean use_16bit_ref = FALSE;
|
||||
gboolean use_delivery_reports;
|
||||
int err;
|
||||
struct ofono_uuid uuid;
|
||||
enum ofono_sms_submit_flag submit_flags;
|
||||
enum sms_datagram_endianess endianess = SMS_DATAGRAM_ENDIANESS_GSM;
|
||||
|
||||
if (bytes == NULL) {
|
||||
__ofono_dbus_pending_reply(&message->pending,
|
||||
__ofono_error_invalid_format(message->pending));
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & OFONO_SMS_DATA_FLAG_USE_LITTLE_ENDIAN)
|
||||
endianess = SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN;
|
||||
|
||||
use_delivery_reports = flags & OFONO_SMS_DATA_FLAG_DELIVERY_REPORT;
|
||||
msg_list = sms_datagram_prepare_with_endianess(to, bytes, len, sms->ref,
|
||||
use_16bit_ref, srcport, dstport, TRUE,
|
||||
use_delivery_reports, endianess);
|
||||
|
||||
if (msg_list == NULL) {
|
||||
__ofono_dbus_pending_reply(&message->pending,
|
||||
__ofono_error_invalid_format(message->pending));
|
||||
return;
|
||||
}
|
||||
|
||||
submit_flags = OFONO_SMS_SUBMIT_FLAG_RETRY;
|
||||
submit_flags |= OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS;
|
||||
|
||||
if (use_delivery_reports)
|
||||
submit_flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;
|
||||
|
||||
err = __ofono_sms_txq_submit(sms, msg_list, submit_flags, &uuid,
|
||||
message_queued, message->pending);
|
||||
|
||||
g_slist_free_full(msg_list, g_free);
|
||||
|
||||
if (err < 0) {
|
||||
__ofono_dbus_pending_reply(&message->pending,
|
||||
__ofono_error_failed(message->pending));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ownership has been transfered to the message queue */
|
||||
message->pending = NULL;
|
||||
|
||||
DBG("SMS data sent");
|
||||
}
|
||||
|
||||
static void sms_send_message_destroy(void *data)
|
||||
{
|
||||
struct sms_message_data *message = data;
|
||||
@@ -1099,6 +1157,49 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *sms_send_data_message(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ofono_sms *sms = data;
|
||||
const char *to;
|
||||
unsigned char *bytes = NULL;
|
||||
struct sms_message_data *message;
|
||||
struct sms_address addr;
|
||||
dbus_int32_t srcport;
|
||||
dbus_int32_t dstport;
|
||||
dbus_uint32_t flags;
|
||||
int len;
|
||||
|
||||
if (!ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
|
||||
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR,
|
||||
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_DATA_MESSAGE, NULL))
|
||||
return __ofono_error_access_denied(msg);
|
||||
|
||||
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
|
||||
&bytes, &len,
|
||||
DBUS_TYPE_INT32, &srcport,
|
||||
DBUS_TYPE_INT32, &dstport,
|
||||
DBUS_TYPE_UINT32, &flags,
|
||||
DBUS_TYPE_INVALID))
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
if (valid_phone_number_format(to) == FALSE)
|
||||
return __ofono_error_invalid_format(msg);
|
||||
|
||||
message = g_new0(struct sms_message_data, 1);
|
||||
message->pending = dbus_message_ref(msg);
|
||||
|
||||
sms_address_from_string(&addr, to);
|
||||
__ofono_sms_filter_chain_send_datagram(sms->filter_chain, &addr,
|
||||
dstport, srcport, bytes, len, flags,
|
||||
sms_send_data_message_submit,
|
||||
sms_send_message_destroy, message);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *sms_get_messages(DBusConnection *conn, DBusMessage *msg,
|
||||
void *data)
|
||||
{
|
||||
@@ -1216,6 +1317,15 @@ static const GDBusMethodTable sms_manager_methods[] = {
|
||||
GDBUS_ARGS({ "to", "s" }, { "text", "s" }),
|
||||
GDBUS_ARGS({ "path", "o" }),
|
||||
sms_send_message) },
|
||||
{ GDBUS_ASYNC_METHOD("SendDataMessage",
|
||||
GDBUS_ARGS(
|
||||
{ "to", "s" },
|
||||
{ "data", "ay" },
|
||||
{ "srcport", "i"},
|
||||
{ "dstport", "i"},
|
||||
{ "flags", "u"}),
|
||||
GDBUS_ARGS({ "path", "o" }),
|
||||
sms_send_data_message) },
|
||||
{ GDBUS_METHOD("GetMessages",
|
||||
NULL, GDBUS_ARGS({ "messages", "a(oa{sv})" }),
|
||||
sms_get_messages) },
|
||||
|
||||
@@ -628,6 +628,10 @@ gboolean sms_decode_address_field(const unsigned char *pdu, int len,
|
||||
if (!next_octet(pdu, len, offset, &addr_len))
|
||||
return FALSE;
|
||||
|
||||
/* According to 23.040 9.1.2.5 Address-Length must not exceed 20 */
|
||||
if (addr_len > 20)
|
||||
return FALSE;
|
||||
|
||||
if (sc && addr_len == 0) {
|
||||
out->address[0] = '\0';
|
||||
return TRUE;
|
||||
@@ -941,10 +945,16 @@ static gboolean decode_submit_report(const unsigned char *pdu, int len,
|
||||
return FALSE;
|
||||
|
||||
if (out->type == SMS_TYPE_SUBMIT_REPORT_ERROR) {
|
||||
if (expected > (int) sizeof(out->submit_err_report.ud))
|
||||
return FALSE;
|
||||
|
||||
out->submit_err_report.udl = udl;
|
||||
memcpy(out->submit_err_report.ud,
|
||||
pdu + offset, expected);
|
||||
} else {
|
||||
if (expected > (int) sizeof(out->submit_ack_report.ud))
|
||||
return FALSE;
|
||||
|
||||
out->submit_ack_report.udl = udl;
|
||||
memcpy(out->submit_ack_report.ud,
|
||||
pdu + offset, expected);
|
||||
@@ -3423,19 +3433,21 @@ static inline GSList *sms_list_append(GSList *l, const struct sms *in)
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepares a datagram for transmission. Breaks up into fragments if
|
||||
* necessary using ref as the concatenated message reference number.
|
||||
* Prepares a datagram for transmission with requested endianess Breaks up
|
||||
* into fragments if necessary using ref as the concatenated message reference
|
||||
* number.
|
||||
* Returns a list of sms messages in order.
|
||||
*
|
||||
* @use_delivery_reports: value for the Status-Report-Request field
|
||||
* (23.040 3.2.9, 9.2.2.2)
|
||||
*/
|
||||
GSList *sms_datagram_prepare(const char *to,
|
||||
GSList *sms_datagram_prepare_with_endianess(const char *to,
|
||||
const unsigned char *data, unsigned int len,
|
||||
guint16 ref, gboolean use_16bit_ref,
|
||||
unsigned short src, unsigned short dst,
|
||||
gboolean use_16bit_port,
|
||||
gboolean use_delivery_reports)
|
||||
gboolean use_delivery_reports,
|
||||
enum sms_datagram_endianess endianess)
|
||||
{
|
||||
struct sms template;
|
||||
unsigned int offset;
|
||||
@@ -3462,10 +3474,22 @@ GSList *sms_datagram_prepare(const char *to,
|
||||
template.submit.ud[0] += 6;
|
||||
template.submit.ud[offset] = SMS_IEI_APPLICATION_ADDRESS_16BIT;
|
||||
template.submit.ud[offset + 1] = 4;
|
||||
template.submit.ud[offset + 2] = (dst & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 3] = dst & 0xff;
|
||||
template.submit.ud[offset + 4] = (src & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 5] = src & 0xff;
|
||||
|
||||
switch (endianess) {
|
||||
case SMS_DATAGRAM_ENDIANESS_GSM:
|
||||
case SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN:
|
||||
template.submit.ud[offset + 2] = (dst & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 3] = dst & 0xff;
|
||||
template.submit.ud[offset + 4] = (src & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 5] = src & 0xff;
|
||||
break;
|
||||
case SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN:
|
||||
template.submit.ud[offset + 2] = dst & 0xff;
|
||||
template.submit.ud[offset + 3] = (dst & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 4] = src & 0xff;
|
||||
template.submit.ud[offset + 5] = (src & 0xff00) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += 6;
|
||||
} else {
|
||||
@@ -3489,8 +3513,18 @@ GSList *sms_datagram_prepare(const char *to,
|
||||
template.submit.ud[0] += 6;
|
||||
template.submit.ud[offset] = SMS_IEI_CONCATENATED_16BIT;
|
||||
template.submit.ud[offset + 1] = 4;
|
||||
template.submit.ud[offset + 2] = (ref & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 3] = ref & 0xff;
|
||||
|
||||
switch (endianess) {
|
||||
case SMS_DATAGRAM_ENDIANESS_GSM:
|
||||
case SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN:
|
||||
template.submit.ud[offset + 2] = (ref & 0xff00) >> 8;
|
||||
template.submit.ud[offset + 3] = ref & 0xff;
|
||||
break;
|
||||
case SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN:
|
||||
template.submit.ud[offset + 2] = ref & 0xff;
|
||||
template.submit.ud[offset + 3] = (ref & 0xff00) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += 6;
|
||||
} else {
|
||||
@@ -3548,6 +3582,28 @@ GSList *sms_datagram_prepare(const char *to,
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepares a datagram for transmission Breaks up into fragments if
|
||||
* necessary using ref as the concatenated message reference number.
|
||||
* Returns a list of sms messages in order.
|
||||
*
|
||||
* @use_delivery_reports: value for the Status-Report-Request field
|
||||
* (23.040 3.2.9, 9.2.2.2)
|
||||
*/
|
||||
|
||||
GSList *sms_datagram_prepare(const char *to,
|
||||
const unsigned char *data, unsigned int len,
|
||||
guint16 ref, gboolean use_16bit_ref,
|
||||
unsigned short src, unsigned short dst,
|
||||
gboolean use_16bit_port,
|
||||
gboolean use_delivery_reports)
|
||||
{
|
||||
return sms_datagram_prepare_with_endianess(to, data, len, ref,
|
||||
use_16bit_ref, src, dst,
|
||||
use_16bit_port, use_delivery_reports,
|
||||
SMS_DATAGRAM_ENDIANESS_GSM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepares the text for transmission. Breaks up into fragments if
|
||||
* necessary using ref as the concatenated message reference number.
|
||||
@@ -4547,13 +4603,11 @@ out:
|
||||
GSList *cbs_optimize_ranges(GSList *ranges)
|
||||
{
|
||||
struct cbs_topic_range *range;
|
||||
unsigned char bitmap[125];
|
||||
unsigned char *bitmap = g_malloc0(CBS_MAX_TOPIC / 8 + 1);
|
||||
GSList *l;
|
||||
unsigned short i;
|
||||
GSList *ret = NULL;
|
||||
|
||||
memset(bitmap, 0, sizeof(bitmap));
|
||||
|
||||
for (l = ranges; l; l = l->next) {
|
||||
range = l->data;
|
||||
|
||||
@@ -4567,7 +4621,7 @@ GSList *cbs_optimize_ranges(GSList *ranges)
|
||||
|
||||
range = NULL;
|
||||
|
||||
for (i = 0; i <= 999; i++) {
|
||||
for (i = 0; i <= CBS_MAX_TOPIC; i++) {
|
||||
int byte_offset = i / 8;
|
||||
int bit = i % 8;
|
||||
|
||||
@@ -4595,6 +4649,7 @@ GSList *cbs_optimize_ranges(GSList *ranges)
|
||||
|
||||
ret = g_slist_reverse(ret);
|
||||
|
||||
g_free(bitmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4607,10 +4662,10 @@ GSList *cbs_extract_topic_ranges(const char *ranges)
|
||||
GSList *tmp;
|
||||
|
||||
while (next_range(ranges, &offset, &min, &max) == TRUE) {
|
||||
if (min < 0 || min > 999)
|
||||
if (min < 0 || min > CBS_MAX_TOPIC)
|
||||
return NULL;
|
||||
|
||||
if (max < 0 || max > 999)
|
||||
if (max < 0 || max > CBS_MAX_TOPIC)
|
||||
return NULL;
|
||||
|
||||
if (max < min)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ofono/types.h>
|
||||
|
||||
#define CBS_MAX_GSM_CHARS 93
|
||||
#define CBS_MAX_TOPIC 9999
|
||||
#define SMS_MSGID_LEN 20
|
||||
|
||||
enum sms_type {
|
||||
@@ -229,6 +230,12 @@ enum cbs_geo_scope {
|
||||
CBS_GEO_SCOPE_CELL_NORMAL
|
||||
};
|
||||
|
||||
enum sms_datagram_endianess {
|
||||
SMS_DATAGRAM_ENDIANESS_GSM,
|
||||
SMS_DATAGRAM_ENDIANESS_BIG_ENDIAN,
|
||||
SMS_DATAGRAM_ENDIANESS_LITTLE_ENDIAN
|
||||
};
|
||||
|
||||
struct sms_address {
|
||||
enum sms_number_type number_type;
|
||||
enum sms_numbering_plan numbering_plan;
|
||||
@@ -574,6 +581,14 @@ GSList *sms_datagram_prepare(const char *to,
|
||||
gboolean use_16bit_port,
|
||||
gboolean use_delivery_reports);
|
||||
|
||||
GSList *sms_datagram_prepare_with_endianess(const char *to,
|
||||
const unsigned char *data, unsigned int len,
|
||||
guint16 ref, gboolean use_16bit_ref,
|
||||
unsigned short src, unsigned short dst,
|
||||
gboolean use_16bit_port,
|
||||
gboolean use_delivery_reports,
|
||||
enum sms_datagram_endianess endianess);
|
||||
|
||||
gboolean cbs_dcs_decode(guint8 dcs, gboolean *udhi, enum sms_class *cls,
|
||||
enum sms_charset *charset, gboolean *compressed,
|
||||
enum cbs_language *language, gboolean *iso639);
|
||||
|
||||
@@ -1738,11 +1738,7 @@ static int voicecall_dial(struct ofono_voicecall *vc, const char *number,
|
||||
|
||||
string_to_phone_number(number, &ph);
|
||||
|
||||
/* No filtering for emergency calls */
|
||||
if (is_emergency_number(vc, number))
|
||||
vc->driver->dial(vc, &ph, clir, cb, vc);
|
||||
else
|
||||
dial_filter(vc, &ph, clir, cb, vc);
|
||||
dial_filter(vc, &ph, clir, cb, vc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2669,9 +2665,9 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
|
||||
if (l) {
|
||||
/* Incoming call was disconnected in the process of being
|
||||
* filtered. voicecall_destroy cancels it. */
|
||||
voicecall_destroy(l->data);
|
||||
vc->incoming_filter_list = g_slist_delete_link
|
||||
(vc->incoming_filter_list, l);
|
||||
voicecall_destroy(l->data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4262,14 +4258,10 @@ static void dial_request(struct ofono_voicecall *vc)
|
||||
struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
|
||||
|
||||
__ofono_modem_inc_emergency_mode(modem);
|
||||
|
||||
/* No filtering for emergency calls */
|
||||
vc->driver->dial(vc, &vc->dial_req->ph,
|
||||
OFONO_CLIR_OPTION_DEFAULT, dial_request_cb, vc);
|
||||
} else {
|
||||
dial_filter(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
|
||||
dial_request_cb, vc);
|
||||
}
|
||||
|
||||
dial_filter(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
|
||||
dial_request_cb, vc);
|
||||
}
|
||||
|
||||
static void dial_req_disconnect_cb(const struct ofono_error *error, void *data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017-2021 Jolla Ltd.
|
||||
* Copyright (C) 2017-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -41,6 +41,7 @@ struct ofono_watch_object {
|
||||
guint imsi_watch_id;
|
||||
guint spn_watch_id;
|
||||
guint netreg_watch_id;
|
||||
guint netreg_status_watch_id;
|
||||
guint gprs_watch_id;
|
||||
};
|
||||
|
||||
@@ -67,6 +68,7 @@ enum ofono_watch_signal {
|
||||
SIGNAL_REG_MCC_CHANGED,
|
||||
SIGNAL_REG_MNC_CHANGED,
|
||||
SIGNAL_REG_NAME_CHANGED,
|
||||
SIGNAL_REG_TECH_CHANGED,
|
||||
SIGNAL_GPRS_CHANGED,
|
||||
SIGNAL_GPRS_SETTINGS_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
@@ -84,6 +86,7 @@ enum ofono_watch_signal {
|
||||
#define SIGNAL_REG_MCC_CHANGED_NAME "ofono-watch-reg-mcc-changed"
|
||||
#define SIGNAL_REG_MNC_CHANGED_NAME "ofono-watch-reg-mnc-changed"
|
||||
#define SIGNAL_REG_NAME_CHANGED_NAME "ofono-watch-reg-name-changed"
|
||||
#define SIGNAL_REG_TECH_CHANGED_NAME "ofono-watch-reg-tech-changed"
|
||||
#define SIGNAL_GPRS_CHANGED_NAME "ofono-watch-gprs-changed"
|
||||
#define SIGNAL_GPRS_SETTINGS_CHANGED_NAME "ofono-watch-gprs-settings-changed"
|
||||
|
||||
@@ -134,11 +137,13 @@ static void ofono_watch_emit_queued_signals(struct ofono_watch_object *self)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_object_ref(self);
|
||||
for (i = 0; self->queued_signals && i < SIGNAL_COUNT; i++) {
|
||||
if (self->queued_signals & ofono_watch_signal_bit(i)) {
|
||||
ofono_watch_signal_emit(self, i);
|
||||
}
|
||||
}
|
||||
g_object_unref(self);
|
||||
}
|
||||
|
||||
static void ofono_watch_iccid_update(struct ofono_watch_object *self,
|
||||
@@ -349,6 +354,7 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
|
||||
struct ofono_watch *watch = &self->pub;
|
||||
struct ofono_netreg *netreg = watch->netreg;
|
||||
enum ofono_netreg_status status = ofono_netreg_get_status(netreg);
|
||||
enum ofono_access_technology act = ofono_netreg_get_technology(netreg);
|
||||
const char *mcc = ofono_netreg_get_mcc(netreg);
|
||||
const char *mnc = ofono_netreg_get_mnc(netreg);
|
||||
const char *name = ofono_netreg_get_name(netreg);
|
||||
@@ -357,6 +363,10 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
|
||||
watch->reg_status = status;
|
||||
ofono_watch_signal_queue(self, SIGNAL_REG_STATUS_CHANGED);
|
||||
}
|
||||
if (watch->reg_tech != act) {
|
||||
watch->reg_tech = act;
|
||||
ofono_watch_signal_queue(self, SIGNAL_REG_TECH_CHANGED);
|
||||
}
|
||||
if (g_strcmp0(self->reg_mcc, mcc)) {
|
||||
g_free(self->reg_mcc);
|
||||
watch->reg_mcc = self->reg_mcc = g_strdup(mcc);
|
||||
@@ -374,17 +384,49 @@ static void ofono_watch_netreg_update(struct ofono_watch_object *self)
|
||||
}
|
||||
}
|
||||
|
||||
static void ofono_watch_netreg_status_notify(int status, int lac, int ci,
|
||||
int tech, const char *mcc, const char *mnc, void *user_data)
|
||||
{
|
||||
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
|
||||
|
||||
ofono_watch_netreg_update(self);
|
||||
ofono_watch_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void ofono_watch_netreg_status_destroy(void *user_data)
|
||||
{
|
||||
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
|
||||
|
||||
ASSERT(self->netreg_status_watch_id);
|
||||
self->netreg_status_watch_id = 0;
|
||||
}
|
||||
|
||||
static void ofono_watch_set_netreg(struct ofono_watch_object *self,
|
||||
struct ofono_netreg *netreg)
|
||||
{
|
||||
struct ofono_watch *watch = &self->pub;
|
||||
|
||||
if (watch->netreg != netreg) {
|
||||
if (self->netreg_status_watch_id) {
|
||||
__ofono_netreg_remove_status_watch(watch->netreg,
|
||||
self->netreg_status_watch_id);
|
||||
/* The destroy callback clears it */
|
||||
ASSERT(!self->netreg_status_watch_id);
|
||||
}
|
||||
|
||||
watch->netreg = netreg;
|
||||
ofono_watch_signal_queue(self, SIGNAL_NETREG_CHANGED);
|
||||
|
||||
if (netreg) {
|
||||
self->netreg_status_watch_id =
|
||||
__ofono_netreg_add_status_watch(netreg,
|
||||
ofono_watch_netreg_status_notify, self,
|
||||
ofono_watch_netreg_status_destroy);
|
||||
}
|
||||
|
||||
ofono_watch_netreg_update(self);
|
||||
ofono_watch_emit_queued_signals(self);
|
||||
}
|
||||
ofono_watch_netreg_update(self);
|
||||
ofono_watch_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void ofono_watch_netreg_notify(struct ofono_atom *atom,
|
||||
@@ -417,6 +459,7 @@ static void ofono_watch_set_gprs(struct ofono_watch_object *self,
|
||||
|
||||
if (watch->gprs != gprs) {
|
||||
watch->gprs = gprs;
|
||||
|
||||
ofono_watch_signal_queue(self, SIGNAL_GPRS_CHANGED);
|
||||
ofono_watch_emit_queued_signals(self);
|
||||
}
|
||||
@@ -730,6 +773,7 @@ ADD_SIGNAL_HANDLER_PROC(reg_status,REG_STATUS)
|
||||
ADD_SIGNAL_HANDLER_PROC(reg_mcc,REG_MCC)
|
||||
ADD_SIGNAL_HANDLER_PROC(reg_mnc,REG_MNC)
|
||||
ADD_SIGNAL_HANDLER_PROC(reg_name,REG_NAME)
|
||||
ADD_SIGNAL_HANDLER_PROC(reg_tech,REG_TECH)
|
||||
ADD_SIGNAL_HANDLER_PROC(gprs,GPRS)
|
||||
|
||||
static void ofono_watch_gprs_settings_signal_cb(struct ofono_watch_object *src,
|
||||
@@ -775,21 +819,6 @@ void ofono_watch_remove_handlers(struct ofono_watch *watch, unsigned long *ids,
|
||||
}
|
||||
}
|
||||
|
||||
void __ofono_watch_netreg_changed(const char *path)
|
||||
{
|
||||
if (path && ofono_watch_table) {
|
||||
struct ofono_watch_object *self =
|
||||
g_hash_table_lookup(ofono_watch_table, path);
|
||||
|
||||
if (self) {
|
||||
g_object_ref(self);
|
||||
ofono_watch_netreg_update(self);
|
||||
ofono_watch_emit_queued_signals(self);
|
||||
g_object_unref(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __ofono_watch_gprs_settings_changed(const char *path,
|
||||
enum ofono_gprs_context_type type,
|
||||
const struct ofono_gprs_primary_context *settings)
|
||||
@@ -813,6 +842,7 @@ static void ofono_watch_object_init(struct ofono_watch_object *self)
|
||||
struct ofono_watch *watch = &self->pub;
|
||||
|
||||
watch->reg_status = OFONO_NETREG_STATUS_NONE;
|
||||
watch->reg_tech = OFONO_ACCESS_TECHNOLOGY_NONE;
|
||||
}
|
||||
|
||||
static void ofono_watch_object_finalize(GObject *object)
|
||||
@@ -847,6 +877,7 @@ static void ofono_watch_object_class_init(OfonoWatchObjectClass *klass)
|
||||
NEW_SIGNAL(klass, REG_MCC);
|
||||
NEW_SIGNAL(klass, REG_MNC);
|
||||
NEW_SIGNAL(klass, REG_NAME);
|
||||
NEW_SIGNAL(klass, REG_TECH);
|
||||
NEW_SIGNAL(klass, GPRS);
|
||||
ofono_watch_signals[SIGNAL_GPRS_SETTINGS_CHANGED] =
|
||||
g_signal_new(SIGNAL_GPRS_SETTINGS_CHANGED_NAME,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2019 Jolla Ltd.
|
||||
* Copyright (C) 2019-2022 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <ofono/watch.h>
|
||||
|
||||
void __ofono_watch_netreg_changed(const char *path);
|
||||
void __ofono_watch_gprs_settings_changed(const char *path,
|
||||
enum ofono_gprs_context_type type,
|
||||
const struct ofono_gprs_primary_context *settings);
|
||||
|
||||
@@ -4,7 +4,8 @@ import sys
|
||||
import dbus
|
||||
|
||||
if (len(sys.argv) < 2):
|
||||
print("Usage: %s [modem] <number> [hide_callerid]" % (sys.argv[0]))
|
||||
print("Usage: %s [modem] <number> [enabled|disabled|default]" % (sys.argv[0]))
|
||||
print("Last argument enables/disables callerid")
|
||||
sys.exit(1)
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
|
||||
@@ -92,9 +92,9 @@ def set_topics(cbs):
|
||||
break
|
||||
|
||||
if topicTemp:
|
||||
if int(topicTemp) > 999:
|
||||
if int(topicTemp) > 9999:
|
||||
invalidData = True
|
||||
print("Invalid Topic ID %s (range 0-999). \
|
||||
print("Invalid Topic ID %s (range 0-9999). \
|
||||
\nCould not register." % topicTemp)
|
||||
|
||||
index = index + 1
|
||||
|
||||
@@ -318,6 +318,28 @@ static struct ofono_cell *test_cell_init_lte(struct ofono_cell *cell)
|
||||
return cell;
|
||||
}
|
||||
|
||||
static struct ofono_cell *test_cell_init_nr(struct ofono_cell *cell)
|
||||
{
|
||||
struct ofono_cell_info_nr *nr = &cell->info.nr;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = OFONO_CELL_TYPE_NR;
|
||||
cell->registered = TRUE;
|
||||
nr->mcc = 244;
|
||||
nr->mnc = 91;
|
||||
nr->nci = 36591883;
|
||||
nr->pci = 309;
|
||||
nr->tac = 4030;
|
||||
nr->nrarfcn = INT_MAX;
|
||||
nr->ssRsrp = 106;
|
||||
nr->ssRsrq = 6;
|
||||
nr->ssSinr = INT_MAX;
|
||||
nr->csiRsrp = 106;
|
||||
nr->csiRsrq = 6;
|
||||
nr->csiSinr = INT_MAX;
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* ==== Misc ==== */
|
||||
|
||||
static void test_misc(void)
|
||||
@@ -540,6 +562,13 @@ static void test_get_all4(void)
|
||||
{
|
||||
struct ofono_cell cell;
|
||||
|
||||
test_get_all(test_cell_init_nr(&cell), "nr");
|
||||
}
|
||||
|
||||
static void test_get_all5(void)
|
||||
{
|
||||
struct ofono_cell cell;
|
||||
|
||||
/* Invalid cell */
|
||||
memset(&cell, 0xff, sizeof(cell));
|
||||
test_get_all(&cell, "unknown");
|
||||
@@ -1145,6 +1174,7 @@ int main(int argc, char *argv[])
|
||||
g_test_add_func(TEST_("GetAll2"), test_get_all2);
|
||||
g_test_add_func(TEST_("GetAll3"), test_get_all3);
|
||||
g_test_add_func(TEST_("GetAll4"), test_get_all4);
|
||||
g_test_add_func(TEST_("GetAll5"), test_get_all5);
|
||||
g_test_add_func(TEST_("GetInterfaceVersion"), test_get_version);
|
||||
g_test_add_func(TEST_("GetType"), test_get_type);
|
||||
g_test_add_func(TEST_("GetRegistered"), test_get_registered);
|
||||
|
||||
@@ -226,6 +226,35 @@ static void test_compare(void)
|
||||
c2 = c1; c2.info.lte.timingAdvance++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
|
||||
/* NR */
|
||||
c1.type = OFONO_CELL_TYPE_NR;
|
||||
c2 = c1;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.mcc++;
|
||||
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
|
||||
c2 = c1; c2.info.nr.mnc++;
|
||||
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
|
||||
c2 = c1; c2.info.nr.nci++;
|
||||
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
|
||||
c2 = c1; c2.info.nr.pci++;
|
||||
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
|
||||
c2 = c1; c2.info.nr.tac++;
|
||||
g_assert(ofono_cell_compare_location(&c1, &c2) < 0);
|
||||
/* Other attributes are not being compared */
|
||||
c2 = c1; c2.info.nr.nrarfcn++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.ssRsrp++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.ssRsrq++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.ssSinr++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.csiRsrp++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.csiRsrq++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
c2 = c1; c2.info.nr.csiSinr++;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
/* Unknown type */
|
||||
c1.type = c2.type = (enum ofono_cell_type)-1;
|
||||
g_assert(!ofono_cell_compare_location(&c1, &c2));
|
||||
|
||||
@@ -75,6 +75,7 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
|
||||
char *file1 = g_strconcat(subdir, "/bar.conf", NULL);
|
||||
GKeyFile *k = g_key_file_new();
|
||||
char *data;
|
||||
char *out_stripped = g_strstrip(g_strdup(out));
|
||||
|
||||
g_assert(!mkdir(subdir, 0700));
|
||||
g_assert(g_file_set_contents(file, conf, -1, NULL));
|
||||
@@ -84,8 +85,9 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
|
||||
g_key_file_set_list_separator(k, ',');
|
||||
ofono_conf_merge_files(k, file);
|
||||
data = g_key_file_to_data(k, NULL, NULL);
|
||||
g_strstrip(data);
|
||||
DBG("\n%s", data);
|
||||
g_assert(!g_strcmp0(data, out));
|
||||
g_assert(!g_strcmp0(data, out_stripped));
|
||||
g_free(data);
|
||||
g_key_file_unref(k);
|
||||
|
||||
@@ -94,6 +96,7 @@ static void test_merge1(const char *conf, const char *conf1, const char *out)
|
||||
remove(subdir);
|
||||
remove(dir);
|
||||
|
||||
g_free(out_stripped);
|
||||
g_free(file);
|
||||
g_free(file1);
|
||||
g_free(dir);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1589,7 +1589,7 @@ static void test_cbs_padding_character(void)
|
||||
static const char *ranges[] = { "1-5, 2, 3, 600, 569-900, 999",
|
||||
"0-20, 33, 44, 50-60, 20-50, 1-5, 5, 3, 5",
|
||||
NULL };
|
||||
static const char *inv_ranges[] = { "1-5, 3333", "1-5, afbcd", "1-5, 3-5,,",
|
||||
static const char *inv_ranges[] = { "1-5, 33333", "1-5, afbcd", "1-5, 3-5,,",
|
||||
"1-5, 3-5, c", NULL };
|
||||
|
||||
static void test_range_minimizer(void)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name: ofono
|
||||
Summary: Open Source Telephony
|
||||
Version: 1.28
|
||||
Version: 1.29
|
||||
Release: 1
|
||||
License: GPLv2
|
||||
URL: https://github.com/sailfishos/ofono
|
||||
|
||||
2
upstream
2
upstream
Submodule upstream updated: 5e597b599c...fe9d22374e
Reference in New Issue
Block a user