mirror of
https://github.com/sailfishos/ofono
synced 2025-11-23 19:09:44 +08:00
Compare commits
41 Commits
mer/1.23+g
...
mer/1.23+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cefc03e5ed | ||
|
|
85d99536ee | ||
|
|
ea36baa4c1 | ||
|
|
b95a089c00 | ||
|
|
c8dbf5494b | ||
|
|
cfb75f473d | ||
|
|
edd91c94eb | ||
|
|
af0ab142e1 | ||
|
|
dffc04d404 | ||
|
|
97b5fcbd87 | ||
|
|
d7e740347f | ||
|
|
1116ca2481 | ||
|
|
4ad02792db | ||
|
|
eddcb88af4 | ||
|
|
f91df7f0fd | ||
|
|
9d220ff9be | ||
|
|
deefa2c454 | ||
|
|
80224b283d | ||
|
|
07e07b6ddc | ||
|
|
bd836b4499 | ||
|
|
6c289b1432 | ||
|
|
296e46487f | ||
|
|
09e98234aa | ||
|
|
0f4cdba932 | ||
|
|
870bac93e9 | ||
|
|
246cd4e1d2 | ||
|
|
ca20b65098 | ||
|
|
8e35a047da | ||
|
|
2b4b5a224d | ||
|
|
50a5f2547e | ||
|
|
d682fcd5fe | ||
|
|
5799320480 | ||
|
|
3eea7c868e | ||
|
|
4844fc6cf9 | ||
|
|
6976366051 | ||
|
|
d3d776837b | ||
|
|
f56c8a33b0 | ||
|
|
ed2f625b8b | ||
|
|
ed62d38632 | ||
|
|
3f433c97c5 | ||
|
|
86d8149c79 |
@@ -278,6 +278,13 @@ Properties boolean Active [readwrite]
|
||||
via this proxy. All other values are left
|
||||
out in this case.
|
||||
|
||||
array{string} ProxyCSCF [readonly, optional]
|
||||
|
||||
Holds the list of P-CSCF (SIP proxy) for this
|
||||
context. Only used by IMS connections.
|
||||
|
||||
This is a Sailfish OS specific extension.
|
||||
|
||||
dict IPv6.Settings [readonly, optional]
|
||||
|
||||
Holds all the IPv6 network settings
|
||||
@@ -304,6 +311,13 @@ Properties boolean Active [readwrite]
|
||||
|
||||
Holds the gateway IP for this connection.
|
||||
|
||||
array{string} ProxyCSCF [readonly, optional]
|
||||
|
||||
Holds the list of P-CSCF (SIP proxy) for this
|
||||
context. Only used by IMS connections.
|
||||
|
||||
This is a Sailfish OS specific extension.
|
||||
|
||||
string MessageProxy [readwrite, MMS only]
|
||||
|
||||
Holds the MMS Proxy setting.
|
||||
|
||||
@@ -373,7 +373,7 @@ static void ril_cell_info_query(struct ril_cell_info *self)
|
||||
static void ril_cell_info_set_rate(struct ril_cell_info *self)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_array_int32_new(1,
|
||||
(self->update_rate_ms > 0) ? self->update_rate_ms : INT_MAX);
|
||||
(self->update_rate_ms >= 0) ? self->update_rate_ms : INT_MAX);
|
||||
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, MAX_RETRIES);
|
||||
grilio_request_set_retry_func(req, ril_cell_info_retry);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2020 Jolla Ltd.
|
||||
* Copyright (C) 2016-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -243,6 +243,7 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
|
||||
dc->dnses = g_strdupv(call->dnses);
|
||||
dc->gateways = g_strdupv(call->gateways);
|
||||
dc->addresses = g_strdupv(call->addresses);
|
||||
dc->pcscf = g_strdupv(call->pcscf);
|
||||
return dc;
|
||||
} else {
|
||||
return NULL;
|
||||
@@ -253,8 +254,9 @@ static void ril_data_call_destroy(struct ril_data_call *call)
|
||||
{
|
||||
g_free(call->ifname);
|
||||
g_strfreev(call->dnses);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->gateways);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->pcscf);
|
||||
}
|
||||
|
||||
void ril_data_call_free(struct ril_data_call *call)
|
||||
@@ -322,8 +324,7 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
|
||||
|
||||
/* RIL_Data_Call_Response_v9 */
|
||||
if (version >= 9) {
|
||||
/* PCSCF */
|
||||
grilio_parser_skip_string(rilp);
|
||||
call->pcscf = grilio_parser_split_utf8(rilp, " ");
|
||||
|
||||
/* RIL_Data_Call_Response_v11 */
|
||||
if (version >= 11) {
|
||||
@@ -354,16 +355,19 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor *vendor,
|
||||
|
||||
if (parsed) {
|
||||
DBG("[status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,"
|
||||
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
|
||||
"mtu=%d,address=%s,dns=%s %s,gateways=%s,pcscf=%s %s]",
|
||||
call->status, call->retry_time,
|
||||
call->cid, call->active,
|
||||
ril_protocol_from_ofono(call->prot),
|
||||
call->ifname, call->mtu,
|
||||
call->addresses ? call->addresses[0] : NULL,
|
||||
call->dnses ? call->dnses[0] : NULL,
|
||||
call->addresses ? call->addresses[0] : "",
|
||||
call->dnses ? call->dnses[0] : "",
|
||||
(call->dnses && call->dnses[0] &&
|
||||
call->dnses[1]) ? call->dnses[1] : "",
|
||||
call->gateways ? call->gateways[0] : NULL);
|
||||
call->gateways ? call->gateways[0] : "",
|
||||
call->pcscf ? call->pcscf[0] : "",
|
||||
(call->pcscf && call->pcscf[0] &&
|
||||
call->pcscf[1]) ? call->pcscf[1] : "");
|
||||
return call;
|
||||
} else {
|
||||
ril_data_call_free(call);
|
||||
@@ -429,7 +433,8 @@ static gboolean ril_data_call_equal(const struct ril_data_call *c1,
|
||||
!g_strcmp0(c1->ifname, c2->ifname) &&
|
||||
gutil_strv_equal(c1->dnses, c2->dnses) &&
|
||||
gutil_strv_equal(c1->gateways, c2->gateways) &&
|
||||
gutil_strv_equal(c1->addresses, c2->addresses);
|
||||
gutil_strv_equal(c1->addresses, c2->addresses) &&
|
||||
gutil_strv_equal(c1->pcscf, c2->pcscf);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -951,7 +956,8 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
|
||||
*
|
||||
* Makes little sense but it is what it is.
|
||||
*/
|
||||
tech = priv->network->data.ril_tech;
|
||||
tech = (setup->profile_id == RIL_DATA_PROFILE_IMS) ?
|
||||
RADIO_TECH_LTE : priv->network->data.ril_tech;
|
||||
if (tech > 2) {
|
||||
tech += 2;
|
||||
} else {
|
||||
@@ -1014,10 +1020,22 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
|
||||
g_new0(struct ril_data_request_setup, 1);
|
||||
struct ril_data_request *req = &setup->req;
|
||||
|
||||
setup->profile_id = (priv->use_data_profiles &&
|
||||
context_type == OFONO_GPRS_CONTEXT_TYPE_MMS) ?
|
||||
priv->mms_data_profile_id :
|
||||
RIL_DATA_PROFILE_DEFAULT;
|
||||
setup->profile_id = RIL_DATA_PROFILE_DEFAULT;
|
||||
if (priv->use_data_profiles) {
|
||||
switch (context_type) {
|
||||
case OFONO_GPRS_CONTEXT_TYPE_MMS:
|
||||
setup->profile_id = priv->mms_data_profile_id;
|
||||
break;
|
||||
case OFONO_GPRS_CONTEXT_TYPE_IMS:
|
||||
setup->profile_id = RIL_DATA_PROFILE_IMS;
|
||||
break;
|
||||
case OFONO_GPRS_CONTEXT_TYPE_ANY:
|
||||
case OFONO_GPRS_CONTEXT_TYPE_INTERNET:
|
||||
case OFONO_GPRS_CONTEXT_TYPE_WAP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setup->apn = g_strdup(ctx->apn);
|
||||
setup->username = g_strdup(ctx->username);
|
||||
setup->password = g_strdup(ctx->password);
|
||||
@@ -1196,6 +1214,31 @@ static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
|
||||
return req;
|
||||
}
|
||||
|
||||
static gboolean ril_data_allow_can_submit(struct ril_data *self)
|
||||
{
|
||||
if (self) {
|
||||
switch (self->priv->options.allow_data) {
|
||||
case RIL_ALLOW_DATA_ENABLED:
|
||||
return TRUE;
|
||||
case RIL_ALLOW_DATA_DISABLED:
|
||||
case RIL_ALLOW_DATA_AUTO:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean ril_data_allow_submit_request(struct ril_data *data,
|
||||
gboolean allow)
|
||||
{
|
||||
if (ril_data_allow_can_submit(data)) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, allow));
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* ril_data
|
||||
*==========================================================================*/
|
||||
@@ -1226,6 +1269,22 @@ void ril_data_remove_handler(struct ril_data *self, gulong id)
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_data_imsi_changed(struct ril_sim_settings *settings,
|
||||
void *user_data)
|
||||
{
|
||||
struct ril_data *self = RIL_DATA(user_data);
|
||||
struct ril_data_priv *priv = self->priv;
|
||||
|
||||
if (!settings->imsi) {
|
||||
/*
|
||||
* Most likely, SIM removal. In any case, no data requests
|
||||
* make sense when IMSI is unavailable.
|
||||
*/
|
||||
ril_data_cancel_all_requests(self);
|
||||
}
|
||||
ril_data_manager_check_network_mode(priv->dm);
|
||||
}
|
||||
|
||||
static void ril_data_settings_changed(struct ril_sim_settings *settings,
|
||||
void *user_data)
|
||||
{
|
||||
@@ -1308,7 +1367,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
|
||||
priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] =
|
||||
ril_sim_settings_add_imsi_changed_handler(settings,
|
||||
ril_data_settings_changed, self);
|
||||
ril_data_imsi_changed, self);
|
||||
priv->settings_event_id[SETTINGS_EVENT_PREF_MODE] =
|
||||
ril_sim_settings_add_pref_mode_changed_handler(settings,
|
||||
ril_data_settings_changed, self);
|
||||
@@ -1466,10 +1525,8 @@ static void ril_data_disallow(struct ril_data *self)
|
||||
*/
|
||||
ril_data_deactivate_all(self);
|
||||
|
||||
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
|
||||
/* Tell rild that the data is now disabled */
|
||||
ril_data_request_queue(ril_data_allow_new(self, FALSE));
|
||||
} else {
|
||||
if (!ril_data_allow_submit_request(self, FALSE)) {
|
||||
priv->flags &= ~RIL_DATA_FLAG_ON;
|
||||
GASSERT(!ril_data_allowed(self));
|
||||
DBG_(self, "data off");
|
||||
@@ -1779,6 +1836,7 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
|
||||
|
||||
static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
||||
{
|
||||
if (self) {
|
||||
GSList *l;
|
||||
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
@@ -1787,6 +1845,7 @@ static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1804,9 +1863,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
||||
ril_data_max_mode(data), TRUE);
|
||||
}
|
||||
|
||||
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, TRUE));
|
||||
} else {
|
||||
if (!ril_data_allow_submit_request(data, TRUE)) {
|
||||
priv->flags |= RIL_DATA_FLAG_ON;
|
||||
GASSERT(ril_data_allowed(data));
|
||||
DBG_(data, "data on");
|
||||
@@ -1830,12 +1887,7 @@ void ril_data_manager_check_data(struct ril_data_manager *self)
|
||||
|
||||
void ril_data_manager_assert_data_on(struct ril_data_manager *self)
|
||||
{
|
||||
if (self) {
|
||||
struct ril_data *data = ril_data_manager_allowed(self);
|
||||
if (data) {
|
||||
ril_data_request_queue(ril_data_allow_new(data, TRUE));
|
||||
}
|
||||
}
|
||||
ril_data_allow_submit_request(ril_data_manager_allowed(self), TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2020 Jolla Ltd.
|
||||
* Copyright (C) 2016-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -40,6 +40,7 @@ struct ril_data_call {
|
||||
char **dnses;
|
||||
char **gateways;
|
||||
char **addresses;
|
||||
char **pcscf;
|
||||
};
|
||||
|
||||
struct ril_data_call_list {
|
||||
|
||||
@@ -34,33 +34,29 @@ struct ril_devmon {
|
||||
GRilIoChannel *channel, struct sailfish_cell_info *cell_info);
|
||||
};
|
||||
|
||||
/* Cell info update intervals */
|
||||
#define RIL_CELL_INFO_INTERVAL_SHORT_MS (2000) /* 2 sec */
|
||||
#define RIL_CELL_INFO_INTERVAL_LONG_MS (30000) /* 30 sec */
|
||||
|
||||
/*
|
||||
* Legacy Device Monitor uses RIL_REQUEST_SCREEN_STATE to tell
|
||||
* the modem when screen turns on and off.
|
||||
*/
|
||||
struct ril_devmon *ril_devmon_ss_new(void);
|
||||
struct ril_devmon *ril_devmon_ss_new(const struct ril_slot_config *config);
|
||||
|
||||
/*
|
||||
* This Device Monitor uses RIL_REQUEST_SEND_DEVICE_STATE to let
|
||||
* the modem choose the right power saving strategy. It basically
|
||||
* mirrors the logic of Android's DeviceStateMonitor class.
|
||||
*/
|
||||
struct ril_devmon *ril_devmon_ds_new(void);
|
||||
struct ril_devmon *ril_devmon_ds_new(const struct ril_slot_config *config);
|
||||
|
||||
/*
|
||||
* This Device Monitor implementation controls network state updates
|
||||
* by sending SET_UNSOLICITED_RESPONSE_FILTER.
|
||||
*/
|
||||
struct ril_devmon *ril_devmon_ur_new(void);
|
||||
struct ril_devmon *ril_devmon_ur_new(const struct ril_slot_config *config);
|
||||
|
||||
/*
|
||||
* This one selects the type based on the RIL version.
|
||||
*/
|
||||
struct ril_devmon *ril_devmon_auto_new(void);
|
||||
struct ril_devmon *ril_devmon_auto_new(const struct ril_slot_config *config);
|
||||
|
||||
/*
|
||||
* This one combines several methods. Takes ownership of ril_devmon objects.
|
||||
|
||||
@@ -65,7 +65,7 @@ static void ril_devmon_auto_free(struct ril_devmon *devmon)
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
struct ril_devmon *ril_devmon_auto_new()
|
||||
struct ril_devmon *ril_devmon_auto_new(const struct ril_slot_config *config)
|
||||
{
|
||||
DevMon *self = g_new0(DevMon, 1);
|
||||
|
||||
@@ -78,8 +78,8 @@ struct ril_devmon *ril_devmon_auto_new()
|
||||
*/
|
||||
self->pub.free = ril_devmon_auto_free;
|
||||
self->pub.start_io = ril_devmon_auto_start_io;
|
||||
self->ss = ril_devmon_ss_new();
|
||||
self->ds = ril_devmon_ds_new();
|
||||
self->ss = ril_devmon_ss_new(config);
|
||||
self->ds = ril_devmon_ds_new(config);
|
||||
return &self->pub;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ typedef struct ril_devmon_ds {
|
||||
MceBattery *battery;
|
||||
MceCharger *charger;
|
||||
MceDisplay *display;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMon;
|
||||
|
||||
typedef struct ril_devmon_ds_io {
|
||||
@@ -86,6 +88,8 @@ typedef struct ril_devmon_ds_io {
|
||||
gulong charger_event_id[CHARGER_EVENT_COUNT];
|
||||
gulong display_event_id[DISPLAY_EVENT_COUNT];
|
||||
guint req_id;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMonIo;
|
||||
|
||||
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
|
||||
@@ -201,8 +205,8 @@ static void ril_devmon_ds_io_set_cell_info_update_interval(DevMonIo *self)
|
||||
(ril_devmon_ds_display_on(self->display) &&
|
||||
(ril_devmon_ds_charging(self->charger) ||
|
||||
ril_devmon_ds_battery_ok(self->battery))) ?
|
||||
RIL_CELL_INFO_INTERVAL_SHORT_MS :
|
||||
RIL_CELL_INFO_INTERVAL_LONG_MS);
|
||||
self->cell_info_interval_short_ms :
|
||||
self->cell_info_interval_long_ms);
|
||||
}
|
||||
|
||||
static void ril_devmon_ds_io_connman_cb(struct ril_connman *connman,
|
||||
@@ -303,6 +307,11 @@ static struct ril_devmon_io *ril_devmon_ds_start_io(struct ril_devmon *devmon,
|
||||
mce_display_add_state_changed_handler(self->display,
|
||||
ril_devmon_ds_io_display_cb, self);
|
||||
|
||||
self->cell_info_interval_short_ms =
|
||||
ds->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
ds->cell_info_interval_long_ms;
|
||||
|
||||
ril_devmon_ds_io_update_low_data(self);
|
||||
ril_devmon_ds_io_update_charging(self);
|
||||
ril_devmon_ds_io_set_cell_info_update_interval(self);
|
||||
@@ -320,7 +329,7 @@ static void ril_devmon_ds_free(struct ril_devmon *devmon)
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
struct ril_devmon *ril_devmon_ds_new()
|
||||
struct ril_devmon *ril_devmon_ds_new(const struct ril_slot_config *config)
|
||||
{
|
||||
DevMon *self = g_new0(DevMon, 1);
|
||||
|
||||
@@ -330,6 +339,10 @@ struct ril_devmon *ril_devmon_ds_new()
|
||||
self->battery = mce_battery_new();
|
||||
self->charger = mce_charger_new();
|
||||
self->display = mce_display_new();
|
||||
self->cell_info_interval_short_ms =
|
||||
config->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
config->cell_info_interval_long_ms;
|
||||
return &self->pub;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ typedef struct ril_devmon_ss {
|
||||
MceBattery *battery;
|
||||
MceCharger *charger;
|
||||
MceDisplay *display;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMon;
|
||||
|
||||
typedef struct ril_devmon_ss_io {
|
||||
@@ -65,6 +67,8 @@ typedef struct ril_devmon_ss_io {
|
||||
gulong charger_event_id[CHARGER_EVENT_COUNT];
|
||||
gulong display_event_id[DISPLAY_EVENT_COUNT];
|
||||
guint req_id;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMonIo;
|
||||
|
||||
inline static DevMon *ril_devmon_ss_cast(struct ril_devmon *pub)
|
||||
@@ -130,8 +134,8 @@ static void ril_devmon_ss_io_set_cell_info_update_interval(DevMonIo *self)
|
||||
sailfish_cell_info_set_update_interval(self->cell_info,
|
||||
(self->display_on && (ril_devmon_ss_charging(self->charger) ||
|
||||
ril_devmon_ss_battery_ok(self->battery))) ?
|
||||
RIL_CELL_INFO_INTERVAL_SHORT_MS :
|
||||
RIL_CELL_INFO_INTERVAL_LONG_MS);
|
||||
self->cell_info_interval_short_ms :
|
||||
self->cell_info_interval_long_ms);
|
||||
}
|
||||
|
||||
static void ril_devmon_ss_io_battery_cb(MceBattery *battery, void *user_data)
|
||||
@@ -212,6 +216,11 @@ static struct ril_devmon_io *ril_devmon_ss_start_io(struct ril_devmon *devmon,
|
||||
mce_display_add_state_changed_handler(self->display,
|
||||
ril_devmon_ss_io_display_cb, self);
|
||||
|
||||
self->cell_info_interval_short_ms =
|
||||
ss->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
ss->cell_info_interval_long_ms;
|
||||
|
||||
ril_devmon_ss_io_send_screen_state(self);
|
||||
ril_devmon_ss_io_set_cell_info_update_interval(self);
|
||||
return &self->pub;
|
||||
@@ -227,7 +236,7 @@ static void ril_devmon_ss_free(struct ril_devmon *devmon)
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
struct ril_devmon *ril_devmon_ss_new()
|
||||
struct ril_devmon *ril_devmon_ss_new(const struct ril_slot_config *config)
|
||||
{
|
||||
DevMon *self = g_new0(DevMon, 1);
|
||||
|
||||
@@ -236,6 +245,10 @@ struct ril_devmon *ril_devmon_ss_new()
|
||||
self->battery = mce_battery_new();
|
||||
self->charger = mce_charger_new();
|
||||
self->display = mce_display_new();
|
||||
self->cell_info_interval_short_ms =
|
||||
config->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
config->cell_info_interval_long_ms;
|
||||
return &self->pub;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ typedef struct ril_devmon_ur {
|
||||
MceBattery *battery;
|
||||
MceCharger *charger;
|
||||
MceDisplay *display;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMon;
|
||||
|
||||
typedef struct ril_devmon_ur_io {
|
||||
@@ -70,6 +72,8 @@ typedef struct ril_devmon_ur_io {
|
||||
gulong charger_event_id[CHARGER_EVENT_COUNT];
|
||||
gulong display_event_id[DISPLAY_EVENT_COUNT];
|
||||
guint req_id;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
} DevMonIo;
|
||||
|
||||
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
|
||||
@@ -136,8 +140,8 @@ static void ril_devmon_ur_io_set_cell_info_update_interval(DevMonIo *self)
|
||||
sailfish_cell_info_set_update_interval(self->cell_info,
|
||||
(self->display_on && (ril_devmon_ur_charging(self->charger) ||
|
||||
ril_devmon_ur_battery_ok(self->battery))) ?
|
||||
RIL_CELL_INFO_INTERVAL_SHORT_MS :
|
||||
RIL_CELL_INFO_INTERVAL_LONG_MS);
|
||||
self->cell_info_interval_short_ms :
|
||||
self->cell_info_interval_long_ms);
|
||||
}
|
||||
|
||||
static void ril_devmon_ur_io_battery_cb(MceBattery *battery, void *user_data)
|
||||
@@ -218,6 +222,11 @@ static struct ril_devmon_io *ril_devmon_ur_start_io(struct ril_devmon *devmon,
|
||||
mce_display_add_state_changed_handler(self->display,
|
||||
ril_devmon_ur_io_display_cb, self);
|
||||
|
||||
self->cell_info_interval_short_ms =
|
||||
ur->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
ur->cell_info_interval_long_ms;
|
||||
|
||||
ril_devmon_ur_io_set_unsol_response_filter(self);
|
||||
ril_devmon_ur_io_set_cell_info_update_interval(self);
|
||||
return &self->pub;
|
||||
@@ -233,7 +242,7 @@ static void ril_devmon_ur_free(struct ril_devmon *devmon)
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
struct ril_devmon *ril_devmon_ur_new()
|
||||
struct ril_devmon *ril_devmon_ur_new(const struct ril_slot_config *config)
|
||||
{
|
||||
DevMon *self = g_new0(DevMon, 1);
|
||||
|
||||
@@ -242,6 +251,10 @@ struct ril_devmon *ril_devmon_ur_new()
|
||||
self->battery = mce_battery_new();
|
||||
self->charger = mce_charger_new();
|
||||
self->display = mce_display_new();
|
||||
self->cell_info_interval_short_ms =
|
||||
config->cell_info_interval_short_ms;
|
||||
self->cell_info_interval_long_ms =
|
||||
config->cell_info_interval_long_ms;
|
||||
return &self->pub;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2019 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#define CTX_ID_NONE ((unsigned int)(-1))
|
||||
|
||||
#define MAX_MTU 1280
|
||||
#define MAX_MMS_MTU 1280
|
||||
|
||||
struct ril_gprs_context_call {
|
||||
struct ril_data_request *req;
|
||||
@@ -108,8 +108,15 @@ static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
|
||||
if (call) {
|
||||
ril_data_call_free(gcd->active_call);
|
||||
gcd->active_call = ril_data_call_dup(call);
|
||||
if (ofono_gprs_context_get_type(gcd->gc) ==
|
||||
OFONO_GPRS_CONTEXT_TYPE_MMS) {
|
||||
/*
|
||||
* Some MMS providers have a problem with MTU
|
||||
* greater than 1280. Let's be safe.
|
||||
*/
|
||||
if (!gcd->mtu_watch) {
|
||||
gcd->mtu_watch = mtu_watch_new(MAX_MTU);
|
||||
gcd->mtu_watch = mtu_watch_new(MAX_MMS_MTU);
|
||||
}
|
||||
}
|
||||
mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
|
||||
ril_data_call_grab(gcd->data, call->cid, gcd);
|
||||
@@ -247,34 +254,59 @@ static void ril_gprs_context_set_gateway(struct ofono_gprs_context *gc,
|
||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
typedef void (*ofono_gprs_context_list_setter_t)(struct ofono_gprs_context *gc,
|
||||
const char **list);
|
||||
|
||||
static void ril_gprs_context_set_servers(struct ofono_gprs_context *gc,
|
||||
char * const *list, ofono_gprs_context_list_setter_t set_ipv4,
|
||||
ofono_gprs_context_list_setter_t set_ipv6)
|
||||
{
|
||||
int i;
|
||||
char * const *list = call->dnses;
|
||||
const char **ip_list = NULL, **ip_ptr = NULL;
|
||||
const char **ipv6_list = NULL, **ipv6_ptr = NULL;
|
||||
const int n = gutil_strv_length(list);
|
||||
const char **ip_dns = g_new0(const char *, n+1);
|
||||
const char **ipv6_dns = g_new0(const char *, n+1);
|
||||
const char **ip_ptr = ip_dns;
|
||||
const char **ipv6_ptr = ipv6_dns;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *addr = list[i];
|
||||
switch (ril_gprs_context_address_family(addr)) {
|
||||
case AF_INET:
|
||||
if (!ip_ptr) {
|
||||
ip_list = g_new0(const char *, n - i + 1);
|
||||
ip_ptr = ip_list;
|
||||
}
|
||||
*ip_ptr++ = addr;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!ipv6_ptr) {
|
||||
ipv6_list = g_new0(const char *, n - i + 1);
|
||||
ipv6_ptr = ipv6_list;
|
||||
}
|
||||
*ipv6_ptr++ = addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc, ip_dns);
|
||||
ofono_gprs_context_set_ipv6_dns_servers(gc, ipv6_dns);
|
||||
set_ipv4(gc, ip_list);
|
||||
set_ipv6(gc, ipv6_list);
|
||||
|
||||
g_free(ip_dns);
|
||||
g_free(ipv6_dns);
|
||||
g_free(ip_list);
|
||||
g_free(ipv6_list);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
{
|
||||
ril_gprs_context_set_servers(gc, call->dnses,
|
||||
ofono_gprs_context_set_ipv4_dns_servers,
|
||||
ofono_gprs_context_set_ipv6_dns_servers);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_proxy_cscf(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
{
|
||||
ril_gprs_context_set_servers(gc, call->pcscf,
|
||||
ofono_gprs_context_set_ipv4_proxy_cscf,
|
||||
ofono_gprs_context_set_ipv6_proxy_cscf);
|
||||
}
|
||||
|
||||
/* Only compares the stuff that's important to us */
|
||||
@@ -282,7 +314,8 @@ static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
|
||||
#define DATA_CALL_ADDRESS_CHANGED (0x02)
|
||||
#define DATA_CALL_GATEWAY_CHANGED (0x04)
|
||||
#define DATA_CALL_DNS_CHANGED (0x08)
|
||||
#define DATA_CALL_ALL_CHANGED (0x0f)
|
||||
#define DATA_CALL_PCSCF_CHANGED (0x10)
|
||||
#define DATA_CALL_ALL_CHANGED (0x1f)
|
||||
static int ril_gprs_context_data_call_change(
|
||||
const struct ril_data_call *c1,
|
||||
const struct ril_data_call *c2)
|
||||
@@ -308,6 +341,10 @@ static int ril_gprs_context_data_call_change(
|
||||
changes |= DATA_CALL_DNS_CHANGED;
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(c1->pcscf, c2->pcscf)) {
|
||||
changes |= DATA_CALL_PCSCF_CHANGED;
|
||||
}
|
||||
|
||||
return changes;
|
||||
} else {
|
||||
return DATA_CALL_ALL_CHANGED;
|
||||
@@ -380,6 +417,11 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
||||
ril_gprs_context_set_dns_servers(gc, call);
|
||||
}
|
||||
|
||||
if (change & DATA_CALL_PCSCF_CHANGED) {
|
||||
DBG("P-CSCF changed");
|
||||
ril_gprs_context_set_proxy_cscf(gc, call);
|
||||
}
|
||||
|
||||
ofono_gprs_context_signal_change(gc, gcd->active_ctx_cid);
|
||||
ril_data_call_free(prev_call);
|
||||
}
|
||||
@@ -421,6 +463,7 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
||||
ril_gprs_context_set_address(gc, call);
|
||||
ril_gprs_context_set_gateway(gc, call);
|
||||
ril_gprs_context_set_dns_servers(gc, call);
|
||||
ril_gprs_context_set_proxy_cscf(gc, call);
|
||||
ril_error_init_ok(&error);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -340,6 +340,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
|
||||
if (md->modem.config.enable_cbs) {
|
||||
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
}
|
||||
ofono_sim_auth_create(modem);
|
||||
}
|
||||
|
||||
static void ril_modem_post_online(struct ofono_modem *modem)
|
||||
|
||||
@@ -436,7 +436,6 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
|
||||
ofono_info("nw select manual: %s%s%s", mcc, mnc, suffix);
|
||||
grilio_request_append_format(req, "%s%s%s", mcc, mnc, suffix);
|
||||
grilio_request_set_timeout(req, nd->network_selection_timeout);
|
||||
grilio_request_set_retry(req, 0, REGISTRATION_MAX_RETRIES);
|
||||
grilio_queue_send_request_full(nd->q, req,
|
||||
RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
|
||||
ril_netreg_register_cb, ril_netreg_cbd_free,
|
||||
@@ -503,7 +502,7 @@ static int ril_netreg_get_signal_strength(struct ril_netreg *nd,
|
||||
signal.qdbm = -4 * tdscdma_dbm;
|
||||
} else if (signal.lte == 99 && rsrp >= 44 && rsrp <= 140) {
|
||||
/* RSRP range: 44 to 140 dBm per 3GPP TS 36.133 */
|
||||
signal.qdbm = -rsrp;
|
||||
signal.qdbm = -4 * rsrp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -444,14 +444,13 @@ static guint ril_network_poll_and_retry(struct ril_network *self, guint id,
|
||||
{
|
||||
struct ril_network_priv *priv = self->priv;
|
||||
|
||||
if (id) {
|
||||
/* Retry right away, don't wait for retry timeout to expire */
|
||||
grilio_channel_retry_request(priv->io, id);
|
||||
} else {
|
||||
/* Don't wait for retry timeout to expire */
|
||||
if (!id || !grilio_channel_retry_request(priv->io, id)) {
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
|
||||
grilio_request_set_retry_func(req, ril_network_retry);
|
||||
grilio_queue_cancel_request(priv->q, id, FALSE);
|
||||
id = grilio_queue_send_request_full(priv->q, req, code, fn,
|
||||
NULL, self);
|
||||
grilio_request_unref(req);
|
||||
@@ -697,7 +696,7 @@ struct ril_network_data_profile *ril_network_data_profile_new
|
||||
ptr += G_ALIGN8(sizeof(*profile));
|
||||
|
||||
profile->profile_id = profile_id;
|
||||
profile->type = RIL_PROFILE_3GPP;
|
||||
profile->type = RIL_PROFILE_COMMON;
|
||||
profile->auth_method = auth_method;
|
||||
profile->proto = context->proto;
|
||||
profile->enabled = TRUE;
|
||||
@@ -826,6 +825,9 @@ static void ril_network_check_data_profiles(struct ril_network *self)
|
||||
const struct ofono_gprs_primary_context* mms =
|
||||
ofono_gprs_context_settings_by_type(gprs,
|
||||
OFONO_GPRS_CONTEXT_TYPE_MMS);
|
||||
const struct ofono_gprs_primary_context* ims =
|
||||
ofono_gprs_context_settings_by_type(gprs,
|
||||
OFONO_GPRS_CONTEXT_TYPE_IMS);
|
||||
GSList *l = NULL;
|
||||
|
||||
if (internet) {
|
||||
@@ -841,6 +843,12 @@ static void ril_network_check_data_profiles(struct ril_network *self)
|
||||
ril_network_data_profile_new(mms,
|
||||
priv->mms_data_profile_id));
|
||||
}
|
||||
if (ims) {
|
||||
DBG_(self, "ims apn \"%s\"", ims->apn);
|
||||
l = g_slist_append(l,
|
||||
ril_network_data_profile_new(ims,
|
||||
RIL_DATA_PROFILE_IMS));
|
||||
}
|
||||
|
||||
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
|
||||
ril_network_data_profiles_free(l);
|
||||
|
||||
@@ -998,8 +998,9 @@ static void ril_export_entries(struct ofono_phonebook *pb,
|
||||
pbd->df_path = usim_path;
|
||||
pbd->df_size = sizeof(usim_path);
|
||||
|
||||
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
|
||||
ofono_sim_read_path(pbd->sim_context, SIM_EFPBR_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
pb_reference_data_cb, pb);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
#define RILMODEM_DEFAULT_USE_DATA_PROFILES FALSE
|
||||
#define RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID RIL_DATA_PROFILE_IMS
|
||||
#define RILMODEM_DEFAULT_SLOT_FLAGS SAILFISH_SLOT_NO_FLAGS
|
||||
#define RILMODEM_DEFAULT_CELL_INFO_INTERVAL_SHORT_MS (2000) /* 2 sec */
|
||||
#define RILMODEM_DEFAULT_CELL_INFO_INTERVAL_LONG_MS (30000) /* 30 sec */
|
||||
|
||||
/* RIL socket transport name and parameters */
|
||||
#define RIL_TRANSPORT_MODEM "modem"
|
||||
@@ -158,6 +160,8 @@
|
||||
#define RILCONF_USE_DATA_PROFILES "useDataProfiles"
|
||||
#define RILCONF_MMS_DATA_PROFILE_ID "mmsDataProfileId"
|
||||
#define RILCONF_DEVMON "deviceStateTracking"
|
||||
#define RILCONF_CELL_INFO_INTERVAL_SHORT_MS "cellInfoIntervalShortMs"
|
||||
#define RILCONF_CELL_INFO_INTERVAL_LONG_MS "cellInfoIntervalLongMs"
|
||||
|
||||
/* Modem error ids */
|
||||
#define RIL_ERROR_ID_RILD_RESTART "rild-restart"
|
||||
@@ -1230,6 +1234,10 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
|
||||
RILMODEM_DEFAULT_FORCE_GSM_WHEN_RADIO_OFF;
|
||||
config->use_data_profiles = RILMODEM_DEFAULT_USE_DATA_PROFILES;
|
||||
config->mms_data_profile_id = RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID;
|
||||
config->cell_info_interval_short_ms =
|
||||
RILMODEM_DEFAULT_CELL_INFO_INTERVAL_SHORT_MS;
|
||||
config->cell_info_interval_long_ms =
|
||||
RILMODEM_DEFAULT_CELL_INFO_INTERVAL_LONG_MS;
|
||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
slot->slot_flags = RILMODEM_DEFAULT_SLOT_FLAGS;
|
||||
@@ -1241,8 +1249,7 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
|
||||
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
|
||||
slot->data_opt.data_call_retry_delay_ms =
|
||||
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
|
||||
|
||||
slot->devmon = ril_devmon_auto_new();
|
||||
slot->devmon = ril_devmon_auto_new(config);
|
||||
slot->watch = ofono_watch_new(dbus_path);
|
||||
slot->watch_event_id[WATCH_EVENT_MODEM] =
|
||||
ofono_watch_add_modem_changed_handler(slot->watch,
|
||||
@@ -1742,6 +1749,26 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
slot->legacy_imei_query ? "on" : "off");
|
||||
}
|
||||
|
||||
/* cellInfoIntervalShortMs */
|
||||
if (ril_config_get_integer(file, group,
|
||||
RILCONF_CELL_INFO_INTERVAL_SHORT_MS,
|
||||
&config->cell_info_interval_short_ms)) {
|
||||
DBG("%s: " RILCONF_CELL_INFO_INTERVAL_SHORT_MS " %d", group,
|
||||
config->cell_info_interval_short_ms);
|
||||
}
|
||||
|
||||
/* cellInfoIntervalLongMs */
|
||||
if (ril_config_get_integer(file, group,
|
||||
RILCONF_CELL_INFO_INTERVAL_LONG_MS,
|
||||
&config->cell_info_interval_long_ms)) {
|
||||
DBG("%s: " RILCONF_CELL_INFO_INTERVAL_LONG_MS " %d",
|
||||
group, config->cell_info_interval_long_ms);
|
||||
}
|
||||
|
||||
/* Replace devmon with a new one with applied settings */
|
||||
ril_devmon_free(slot->devmon);
|
||||
slot->devmon = NULL;
|
||||
|
||||
/* deviceStateTracking */
|
||||
if (ril_config_get_mask(file, group, RILCONF_DEVMON, &ival,
|
||||
"ds", RIL_DEVMON_DS,
|
||||
@@ -1750,11 +1777,16 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
int n = 0;
|
||||
struct ril_devmon *devmon[3];
|
||||
|
||||
if (ival & RIL_DEVMON_DS) devmon[n++] = ril_devmon_ds_new();
|
||||
if (ival & RIL_DEVMON_SS) devmon[n++] = ril_devmon_ss_new();
|
||||
if (ival & RIL_DEVMON_UR) devmon[n++] = ril_devmon_ur_new();
|
||||
if (ival & RIL_DEVMON_DS) {
|
||||
devmon[n++] = ril_devmon_ds_new(config);
|
||||
}
|
||||
if (ival & RIL_DEVMON_SS) {
|
||||
devmon[n++] = ril_devmon_ss_new(config);
|
||||
}
|
||||
if (ival & RIL_DEVMON_UR) {
|
||||
devmon[n++] = ril_devmon_ur_new(config);
|
||||
}
|
||||
DBG("%s: " RILCONF_DEVMON " 0x%x", group, ival);
|
||||
ril_devmon_free(slot->devmon);
|
||||
slot->devmon = ril_devmon_combine(devmon, n);
|
||||
} else {
|
||||
/* Try special values */
|
||||
@@ -1762,13 +1794,14 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
if (sval) {
|
||||
if (!g_ascii_strcasecmp(sval, "none")) {
|
||||
DBG("%s: " RILCONF_DEVMON " %s", group, sval);
|
||||
ril_devmon_free(slot->devmon);
|
||||
slot->devmon = NULL;
|
||||
} else if (!g_ascii_strcasecmp(sval, "auto")) {
|
||||
DBG("%s: " RILCONF_DEVMON " %s", group, sval);
|
||||
/* This is the default */
|
||||
slot->devmon = ril_devmon_auto_new(config);
|
||||
}
|
||||
g_free(sval);
|
||||
} else {
|
||||
/* This is the default */
|
||||
slot->devmon = ril_devmon_auto_new(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2336,7 +2369,6 @@ static int ril_plugin_init(void)
|
||||
static void ril_plugin_exit(void)
|
||||
{
|
||||
DBG("");
|
||||
GASSERT(ril_driver);
|
||||
|
||||
ofono_ril_transport_unregister(&ril_socket_transport);
|
||||
ofono_modem_driver_unregister(&ril_modem_driver);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2019 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include <ofono/watch.h>
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include "simutil.h"
|
||||
#include "util.h"
|
||||
#include "ofono.h"
|
||||
@@ -86,6 +88,7 @@ struct ril_sim {
|
||||
gboolean empty_pin_query_allowed;
|
||||
gboolean inserted;
|
||||
guint idle_id; /* Used by register and SIM reset callbacks */
|
||||
guint list_apps_id;
|
||||
gulong card_event_id[SIM_CARD_EVENT_COUNT];
|
||||
gulong io_event_id[IO_EVENT_COUNT];
|
||||
guint query_pin_retries_id;
|
||||
@@ -118,12 +121,25 @@ struct ril_sim_cbd_io {
|
||||
ofono_sim_write_cb_t write;
|
||||
ofono_sim_imsi_cb_t imsi;
|
||||
ofono_query_facility_lock_cb_t query_facility_lock;
|
||||
ofono_sim_open_channel_cb_t open_channel;
|
||||
ofono_sim_close_channel_cb_t close_channel;
|
||||
gpointer ptr;
|
||||
} cb;
|
||||
gpointer data;
|
||||
guint req_id;
|
||||
};
|
||||
|
||||
struct ril_sim_session_cbd {
|
||||
struct ril_sim *sd;
|
||||
struct ril_sim_card *card;
|
||||
ofono_sim_logical_access_cb_t cb;
|
||||
gpointer data;
|
||||
int ref_count;
|
||||
int session_id;
|
||||
int cla;
|
||||
guint req_id;
|
||||
};
|
||||
|
||||
struct ril_sim_pin_cbd {
|
||||
struct ril_sim *sd;
|
||||
ofono_sim_lock_unlock_cb_t cb;
|
||||
@@ -150,6 +166,16 @@ struct ril_sim_retry_query {
|
||||
GRilIoRequest *(*new_req)(struct ril_sim *sd);
|
||||
};
|
||||
|
||||
/* TS 102.221 */
|
||||
#define APP_TEMPLATE_TAG 0x61
|
||||
#define APP_ID_TAG 0x4F
|
||||
|
||||
struct ril_sim_list_apps {
|
||||
struct ril_sim *sd;
|
||||
ofono_sim_list_apps_cb_t cb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
|
||||
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
|
||||
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
|
||||
@@ -218,6 +244,45 @@ static void ril_sim_cbd_io_start(struct ril_sim_cbd_io *cbd, GRilIoRequest* req,
|
||||
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
|
||||
}
|
||||
|
||||
static struct ril_sim_session_cbd *ril_sim_session_cbd_new(struct ril_sim *sd,
|
||||
int session_id, int cla, ofono_sim_logical_access_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = g_new0(struct ril_sim_session_cbd, 1);
|
||||
|
||||
cbd->sd = sd;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
cbd->card = ril_sim_card_ref(sd->card);
|
||||
cbd->session_id = session_id;
|
||||
cbd->cla = cla;
|
||||
cbd->ref_count = 1;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_sim_session_cbd_unref(void *data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = data;
|
||||
|
||||
if (--(cbd->ref_count) < 1) {
|
||||
ril_sim_card_sim_io_finished(cbd->card, cbd->req_id);
|
||||
ril_sim_card_unref(cbd->card);
|
||||
g_free(cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_session_cbd_start(struct ril_sim_session_cbd *cbd,
|
||||
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc cb)
|
||||
{
|
||||
struct ril_sim *sd = cbd->sd;
|
||||
const guint finished_req = cbd->req_id;
|
||||
|
||||
cbd->ref_count++;
|
||||
cbd->req_id = grilio_queue_send_request_full(sd->q, req, code, cb,
|
||||
ril_sim_session_cbd_unref, cbd);
|
||||
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
|
||||
ril_sim_card_sim_io_finished(cbd->card, finished_req);
|
||||
}
|
||||
|
||||
static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
|
||||
void *user_data)
|
||||
{
|
||||
@@ -307,30 +372,13 @@ static void ril_sim_append_path(struct ril_sim *sd, GRilIoRequest *req,
|
||||
grilio_request_append_utf8(req, hex_path);
|
||||
DBG_(sd, "%s", hex_path);
|
||||
g_free(hex_path);
|
||||
} else if (fileid == SIM_EF_ICCID_FILEID || fileid == SIM_EFPL_FILEID) {
|
||||
/*
|
||||
* Special catch-all for EF_ICCID (unique card ID)
|
||||
* and EF_PL files which exist in the root directory.
|
||||
* As the sim_info_cb function may not have yet
|
||||
* recorded the app_type for the SIM, and the path
|
||||
* for both files is the same for 2g|3g, just hard-code.
|
||||
*
|
||||
* See 'struct ef_db' in:
|
||||
* ../../src/simutil.c for more details.
|
||||
*/
|
||||
DBG_(sd, "%s", ROOTMF);
|
||||
grilio_request_append_utf8(req, ROOTMF);
|
||||
} else {
|
||||
/*
|
||||
* The only known case of this is EFPHASE_FILED (0x6FAE).
|
||||
* The ef_db table ( see /src/simutil.c ) entry for
|
||||
* EFPHASE contains a value of 0x0000 for it's
|
||||
* 'parent3g' member. This causes a NULL path to
|
||||
* be returned.
|
||||
* Catch-all for EF_ICCID, EF_PL and other files absent
|
||||
* from ef_db table in src/simutil.c, hard-code ROOTMF.
|
||||
*/
|
||||
|
||||
DBG_(sd, "returning empty path.");
|
||||
grilio_request_append_utf8(req, NULL);
|
||||
DBG_(sd, "%s (default)", ROOTMF);
|
||||
grilio_request_append_utf8(req, ROOTMF);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1422,6 +1470,294 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_list_apps_cb(void *data)
|
||||
{
|
||||
struct ril_sim_list_apps *rd = data;
|
||||
struct ril_sim *sd = rd->sd;
|
||||
const struct ril_sim_card_status *status = sd->card->status;
|
||||
struct ofono_error error;
|
||||
|
||||
GASSERT(sd->list_apps_id);
|
||||
sd->list_apps_id = 0;
|
||||
|
||||
if (status) {
|
||||
int i, n = status->num_apps;
|
||||
GByteArray *tlv = g_byte_array_sized_new(n * 20);
|
||||
|
||||
/* Reconstruct EFdir contents */
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *hex = status->apps[i].aid;
|
||||
gsize hex_len = hex ? strlen(hex) : 0;
|
||||
long aid_size;
|
||||
guint8 aid[16];
|
||||
|
||||
if (hex_len >= 2 && hex_len <= 2 * sizeof(aid) &&
|
||||
!(hex_len & 0x01) && decode_hex_own_buf(hex,
|
||||
hex_len, &aid_size, 0, aid)) {
|
||||
guint8 buf[4];
|
||||
|
||||
/*
|
||||
* TS 102.221
|
||||
* 13 Application independent files
|
||||
* 13.1 EFdir
|
||||
*
|
||||
* Application template TLV object.
|
||||
*/
|
||||
buf[0] = APP_TEMPLATE_TAG;
|
||||
buf[1] = (guint8)(aid_size + 2);
|
||||
buf[2] = APP_ID_TAG;
|
||||
buf[3] = (guint8)(aid_size);
|
||||
g_byte_array_append(tlv, buf, sizeof(buf));
|
||||
g_byte_array_append(tlv, aid, aid_size);
|
||||
}
|
||||
}
|
||||
DBG_(sd, "reporting %u apps %u bytes", n, tlv->len);
|
||||
rd->cb(ril_error_ok(&error), tlv->data, tlv->len, rd->data);
|
||||
g_byte_array_unref(tlv);
|
||||
} else {
|
||||
DBG_(sd, "no SIM card, no apps");
|
||||
rd->cb(ril_error_failure(&error), NULL, 0, rd->data);
|
||||
}
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_sim_list_apps(struct ofono_sim *sim,
|
||||
ofono_sim_list_apps_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_list_apps *rd = g_new(struct ril_sim_list_apps, 1);
|
||||
|
||||
rd->sd = sd;
|
||||
rd->cb = cb;
|
||||
rd->data = data;
|
||||
if (sd->list_apps_id) {
|
||||
g_source_remove(sd->list_apps_id);
|
||||
}
|
||||
sd->list_apps_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||
ril_sim_list_apps_cb, rd, g_free);
|
||||
}
|
||||
|
||||
static void ril_sim_open_channel_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_cbd_io *cbd = user_data;
|
||||
ofono_sim_open_channel_cb_t cb = cbd->cb.open_channel;
|
||||
struct ofono_error error;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
guint32 n, session_id;
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_uint32(&rilp, &n) && n >= 1 &&
|
||||
grilio_parser_get_uint32(&rilp, &session_id)) {
|
||||
DBG_(cbd->sd, "%u", session_id);
|
||||
cb(ril_error_ok(&error), session_id, cbd->data);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ofono_error("Open logical channel failure: %s",
|
||||
ril_error_to_string(status));
|
||||
}
|
||||
|
||||
cb(ril_error_failure(&error), 0, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sim_open_channel(struct ofono_sim *sim,
|
||||
const unsigned char *aid, unsigned int len,
|
||||
ofono_sim_open_channel_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
char *aid_hex = encode_hex(aid, len, 0);
|
||||
|
||||
DBG_(sd, "%s", aid_hex);
|
||||
grilio_request_append_utf8(req, aid_hex);
|
||||
grilio_request_append_int32(req, 0);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_OPEN_CHANNEL,
|
||||
ril_sim_open_channel_cb);
|
||||
grilio_request_unref(req);
|
||||
g_free(aid_hex);
|
||||
}
|
||||
|
||||
static void ril_sim_close_channel_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_cbd_io *cbd = user_data;
|
||||
struct ofono_error error;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
ril_error_init_ok(&error);
|
||||
} else {
|
||||
ofono_error("Close logical channel failure: %s",
|
||||
ril_error_to_string(status));
|
||||
ril_error_init_failure(&error);
|
||||
}
|
||||
cbd->cb.close_channel(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sim_close_channel(struct ofono_sim *sim, int session_id,
|
||||
ofono_sim_close_channel_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
DBG_(sd, "%u", session_id);
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, session_id);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_CLOSE_CHANNEL,
|
||||
ril_sim_close_channel_cb);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_get_results_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = user_data;
|
||||
ofono_sim_logical_access_cb_t cb = cbd->cb;
|
||||
struct ril_sim_io_response *res;
|
||||
struct ofono_error err;
|
||||
|
||||
res = ril_sim_parse_io_response(data, len);
|
||||
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
|
||||
cb(ril_error_ok(&err), res->data, res->data_len, cbd->data);
|
||||
} else if (res) {
|
||||
cb(ril_error_sim(&err, res->sw1, res->sw2), NULL, 0, cbd->data);
|
||||
} else {
|
||||
cb(ril_error_failure(&err), NULL, 0, cbd->data);
|
||||
}
|
||||
ril_sim_io_response_free(res);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_transmit(struct ril_sim_session_cbd *cbd,
|
||||
int ins, int p1, int p2, int p3, const char *hex_data,
|
||||
GRilIoChannelResponseFunc cb)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
DBG_(cbd->sd, "session=%u,cmd=%02X,%02X,%02X,%02X,%02X,%s",
|
||||
cbd->session_id, cbd->cla, ins, p1, p2, p3,
|
||||
hex_data ? hex_data : "");
|
||||
grilio_request_append_int32(req, cbd->session_id);
|
||||
grilio_request_append_int32(req, cbd->cla);
|
||||
grilio_request_append_int32(req, ins);
|
||||
grilio_request_append_int32(req, p1);
|
||||
grilio_request_append_int32(req, p2);
|
||||
grilio_request_append_int32(req, p3);
|
||||
grilio_request_append_utf8(req, hex_data);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
ril_sim_session_cbd_start(cbd, req,
|
||||
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, cb);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_sim_logical_access_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_session_cbd *cbd = user_data;
|
||||
ofono_sim_logical_access_cb_t cb = cbd->cb;
|
||||
struct ril_sim_io_response *res;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(cbd->sd, "");
|
||||
cbd->req_id = 0;
|
||||
res = ril_sim_parse_io_response(data, len);
|
||||
if (res && status == RIL_E_SUCCESS) {
|
||||
/*
|
||||
* TS 102 221
|
||||
* 7.3.1.1.5.2 Case 4 commands
|
||||
*
|
||||
* If the UICC receives a case 4 command, after processing
|
||||
* the data sent with the C-APDU, it shall return:
|
||||
*
|
||||
* a) procedure bytes '61 xx' instructing the transport
|
||||
* layer of the terminal to issue a GET RESPONSE command
|
||||
* with a maximum length of 'xx'; or
|
||||
* b) status indicating a warning or error condition (but
|
||||
* not SW1 SW2 = '90 00').
|
||||
*
|
||||
* The GET RESPONSE command so issued is then treated as
|
||||
* described for case 2 commands.
|
||||
*/
|
||||
if (res->sw1 == 0x61) {
|
||||
ril_sim_logical_access_transmit(cbd,
|
||||
CMD_GET_RESPONSE, 0, 0, res->sw2, NULL,
|
||||
ril_sim_logical_access_get_results_cb);
|
||||
} else if (ril_sim_io_response_ok(res)) {
|
||||
cb(ril_error_ok(&error), res->data, res->data_len,
|
||||
cbd->data);
|
||||
} else {
|
||||
cb(ril_error_sim(&error, res->sw1, res->sw2), NULL, 0,
|
||||
cbd->data);
|
||||
}
|
||||
} else {
|
||||
cb(ril_error_failure(&error), NULL, 0, cbd->data);
|
||||
}
|
||||
ril_sim_io_response_free(res);
|
||||
}
|
||||
|
||||
static void ril_sim_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)
|
||||
{
|
||||
/* SIM Command APDU: CLA INS P1 P2 P3 Data */
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
const char* hex_data;
|
||||
char *tmp;
|
||||
struct ril_sim_session_cbd *cbd = ril_sim_session_cbd_new(sd,
|
||||
session_id, pdu[0], cb, data);
|
||||
|
||||
GASSERT(len >= 5);
|
||||
if (len > 5) {
|
||||
hex_data = tmp = encode_hex(pdu + 5, len - 5, 0);
|
||||
} else {
|
||||
tmp = NULL;
|
||||
hex_data = "";
|
||||
}
|
||||
|
||||
ril_sim_logical_access_transmit(cbd, pdu[1], pdu[2], pdu[3], pdu[4],
|
||||
hex_data, ril_sim_logical_access_cb);
|
||||
ril_sim_session_cbd_unref(cbd);
|
||||
g_free(tmp);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_binary(struct ofono_sim *sim, int session,
|
||||
int fileid, int start, int length,
|
||||
const unsigned char *path, unsigned int path_len,
|
||||
ofono_sim_read_cb_t cb, void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_binary not implemented");
|
||||
cb(ril_error_failure(&error), NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_record(struct ofono_sim *sim, int session_id,
|
||||
int fileid, int record, int length,
|
||||
const unsigned char *path, unsigned int path_len,
|
||||
ofono_sim_read_cb_t cb, void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_record not implemented");
|
||||
cb(ril_error_failure(&error), NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_session_read_info(struct ofono_sim *sim, int session_id,
|
||||
int fileid, const unsigned char *path,
|
||||
unsigned int path_len, ofono_sim_file_info_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
|
||||
ofono_error("session_read_info not implemented");
|
||||
cb(ril_error_failure(&error), -1, -1, -1, NULL, 0, data);
|
||||
}
|
||||
|
||||
static void ril_sim_refresh_cb(GRilIoChannel *io, guint code,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
@@ -1503,6 +1839,9 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
grilio_queue_cancel_all(sd->q, FALSE);
|
||||
ofono_sim_set_data(sim, NULL);
|
||||
|
||||
if (sd->list_apps_id) {
|
||||
g_source_remove(sd->list_apps_id);
|
||||
}
|
||||
if (sd->idle_id) {
|
||||
g_source_remove(sd->idle_id);
|
||||
}
|
||||
@@ -1547,7 +1886,14 @@ const struct ofono_sim_driver ril_sim_driver = {
|
||||
.reset_passwd = ril_sim_pin_send_puk,
|
||||
.change_passwd = ril_sim_change_passwd,
|
||||
.query_pin_retries = ril_sim_query_pin_retries,
|
||||
.query_facility_lock = ril_sim_query_facility_lock
|
||||
.query_facility_lock = ril_sim_query_facility_lock,
|
||||
.list_apps = ril_sim_list_apps,
|
||||
.open_channel2 = ril_sim_open_channel,
|
||||
.close_channel = ril_sim_close_channel,
|
||||
.session_read_binary = ril_sim_session_read_binary,
|
||||
.session_read_record = ril_sim_session_read_record,
|
||||
.session_read_info = ril_sim_session_read_info,
|
||||
.logical_access = ril_sim_logical_access
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -231,6 +231,12 @@ socket=/dev/socket/rild
|
||||
#
|
||||
#lteNetworkMode=9
|
||||
|
||||
# UMTS network mode.
|
||||
#
|
||||
# Default 3 (PREF_NET_TYPE_GSM_WCDMA_AUTO)
|
||||
#
|
||||
#umtsNetworkMode=3
|
||||
|
||||
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
|
||||
#
|
||||
# Default 20000 (20 seconds)
|
||||
@@ -339,3 +345,29 @@ socket=/dev/socket/rild
|
||||
# Default true (false for MTK RILs)
|
||||
#
|
||||
#forceGsmWhenRadioOff=true
|
||||
|
||||
# Configures a period between RIL_UNSOL_CELL_INFO_LIST events when the device
|
||||
# is awake. Possible values are:
|
||||
#
|
||||
# 0 = invoke RIL_UNSOL_CELL_INFO_LIST when any of the reported information
|
||||
# changes
|
||||
# 1..INT_MAX-1 (2147483646) = sets update period in milliseconds
|
||||
# negative value or INT_MAX = never issue a RIL_UNSOL_CELL_INFO_LIST
|
||||
#
|
||||
# On MediaTek devices the period of RIL_UNSOL_CELL_INFO_LIST events can't be
|
||||
# configured. The parameter RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE has
|
||||
# non-standard meaning:
|
||||
#
|
||||
# 0 = enable RIL_UNSOL_CELL_INFO_LIST
|
||||
# any other value = disable RIL_UNSOL_CELL_INFO_LIST
|
||||
#
|
||||
# Default 2000
|
||||
#
|
||||
#cellInfoIntervalShortMs=2000
|
||||
|
||||
# Configures period between RIL_UNSOL_CELL_INFO_LIST events when the device is
|
||||
# in a power saving mode. For possible values, look cellInfoIntervalShortMs.
|
||||
#
|
||||
# Default 30000
|
||||
#
|
||||
#cellInfoIntervalLongMs=30000
|
||||
|
||||
@@ -79,6 +79,8 @@ struct ril_slot_config {
|
||||
guint mms_data_profile_id;
|
||||
GUtilInts *local_hangup_reasons;
|
||||
GUtilInts *remote_hangup_reasons;
|
||||
int cell_info_interval_short_ms;
|
||||
int cell_info_interval_long_ms;
|
||||
};
|
||||
|
||||
#endif /* RIL_TYPES_H */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -128,6 +129,8 @@ void ofono_gprs_context_set_ipv4_gateway(struct ofono_gprs_context *gc,
|
||||
const char *gateway);
|
||||
void ofono_gprs_context_set_ipv4_dns_servers(struct ofono_gprs_context *gc,
|
||||
const char **dns);
|
||||
void ofono_gprs_context_set_ipv4_proxy_cscf(struct ofono_gprs_context *gc,
|
||||
const char **pcscf); /* Since mer/1.23+git30 */
|
||||
|
||||
void ofono_gprs_context_set_ipv6_address(struct ofono_gprs_context *gc,
|
||||
const char *address);
|
||||
@@ -137,6 +140,8 @@ void ofono_gprs_context_set_ipv6_gateway(struct ofono_gprs_context *gc,
|
||||
const char *gateway);
|
||||
void ofono_gprs_context_set_ipv6_dns_servers(struct ofono_gprs_context *gc,
|
||||
const char **dns);
|
||||
void ofono_gprs_context_set_ipv6_proxy_cscf(struct ofono_gprs_context *gc,
|
||||
const char **pcscf); /* Since mer/1.23+git30 */
|
||||
|
||||
void ofono_gprs_context_signal_change(struct ofono_gprs_context *gc,
|
||||
unsigned int cid);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -210,6 +211,10 @@ 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 */
|
||||
void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid,
|
||||
unsigned int len, ofono_sim_open_channel_cb_t cb,
|
||||
void *data);
|
||||
};
|
||||
|
||||
int ofono_sim_driver_register(const struct ofono_sim_driver *d);
|
||||
|
||||
@@ -495,8 +495,6 @@ static void hfp_ag_enable(DBusConnection *conn)
|
||||
connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
g_free, connection_destroy);
|
||||
|
||||
ofono_handsfree_audio_ref();
|
||||
|
||||
hfp_ag_enabled = TRUE;
|
||||
}
|
||||
|
||||
@@ -525,7 +523,6 @@ static void hfp_ag_disable(DBusConnection *conn)
|
||||
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
|
||||
BLUEZ_PROFILE_INTERFACE);
|
||||
ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
|
||||
ofono_handsfree_audio_unref();
|
||||
}
|
||||
|
||||
hfp_ag_enabled = FALSE;
|
||||
@@ -545,13 +542,14 @@ static int hfp_ag_init(void)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
|
||||
hfp_ag_enable(conn);
|
||||
|
||||
/* g_dbus_add_service_watch immediately checks for bluetooth service
|
||||
* and calls connect callback if the service exists. */
|
||||
service_watch_id = g_dbus_add_service_watch(conn, "org.bluez",
|
||||
bluez_connect_cb,
|
||||
bluez_disconnect_cb,
|
||||
NULL, NULL);
|
||||
|
||||
ofono_handsfree_audio_ref();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -565,6 +563,7 @@ static void hfp_ag_exit(void)
|
||||
}
|
||||
|
||||
hfp_ag_disable(conn);
|
||||
ofono_handsfree_audio_unref();
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins",
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include <ofono/handsfree.h>
|
||||
#include <ofono/handsfree-audio.h>
|
||||
#include <ofono/siri.h>
|
||||
#include <ofono.h>
|
||||
|
||||
#include <drivers/atmodem/atutil.h>
|
||||
#include <drivers/hfpmodem/slc.h>
|
||||
@@ -833,8 +832,6 @@ static int hfp_init(void)
|
||||
if (DBUS_TYPE_UNIX_FD < 0)
|
||||
return -EBADF;
|
||||
|
||||
__ofono_handsfree_audio_manager_init();
|
||||
|
||||
/* Registers External Profile handler */
|
||||
if (!g_dbus_register_interface(conn, HFP_EXT_PROFILE_PATH,
|
||||
BLUEZ_PROFILE_INTERFACE,
|
||||
@@ -890,8 +887,6 @@ static void hfp_exit(void)
|
||||
g_dbus_client_unref(bluez);
|
||||
|
||||
ofono_handsfree_audio_unref();
|
||||
|
||||
__ofono_handsfree_audio_manager_cleanup();
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(hfp_bluez5, "External Hands-Free Profile Plugin", VERSION,
|
||||
|
||||
@@ -121,6 +121,30 @@ void __ofono_dbus_queue_request(struct ofono_dbus_queue *q,
|
||||
}
|
||||
}
|
||||
|
||||
static void __ofono_dbus_queue_submit_next(struct ofono_dbus_queue *q)
|
||||
{
|
||||
struct ofono_dbus_queue_request *next = q->requests;
|
||||
|
||||
while (next) {
|
||||
struct ofono_dbus_queue_request *done;
|
||||
DBusMessage *reply = next->fn(next->msg, next->data);
|
||||
|
||||
/* The request has been sent, no reply yet */
|
||||
if (!reply)
|
||||
break;
|
||||
|
||||
/* The request has completed synchronously */
|
||||
done = next;
|
||||
next = done->next;
|
||||
q->requests = next;
|
||||
done->next = NULL;
|
||||
|
||||
/* Send the reply */
|
||||
__ofono_dbus_pending_reply(&done->msg, reply);
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
}
|
||||
}
|
||||
|
||||
/* Consumes one reference to the reply */
|
||||
void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
|
||||
DBusMessage *reply)
|
||||
@@ -150,20 +174,7 @@ void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
|
||||
/* Submit the next request if there is any */
|
||||
while (next && reply) {
|
||||
reply = next->fn(next->msg, next->data);
|
||||
if (reply) {
|
||||
/* The request has completed synchronously */
|
||||
done = next;
|
||||
next = done->next;
|
||||
q->requests = next;
|
||||
done->next = NULL;
|
||||
|
||||
/* Send the reply */
|
||||
__ofono_dbus_pending_reply(&done->msg, reply);
|
||||
__ofono_dbus_queue_req_free(done);
|
||||
}
|
||||
}
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
}
|
||||
|
||||
void __ofono_dbus_queue_reply_ok(struct ofono_dbus_queue *q)
|
||||
@@ -250,8 +261,10 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
|
||||
* Find all other requests with the same handler and the same data
|
||||
* and complete those too (except when the handler is NULL)
|
||||
*/
|
||||
if (!handler)
|
||||
if (!handler) {
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
return;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
req = q->requests;
|
||||
@@ -274,6 +287,7 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
|
||||
|
||||
req = next;
|
||||
}
|
||||
__ofono_dbus_queue_submit_next(q);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -97,6 +97,7 @@ struct ipv4_settings {
|
||||
char *netmask;
|
||||
char *gateway;
|
||||
char **dns;
|
||||
char **pcscf;
|
||||
char *proxy;
|
||||
};
|
||||
|
||||
@@ -105,6 +106,7 @@ struct ipv6_settings {
|
||||
unsigned char prefix_len;
|
||||
char *gateway;
|
||||
char **dns;
|
||||
char **pcscf;
|
||||
};
|
||||
|
||||
struct context_settings {
|
||||
@@ -410,6 +412,7 @@ static void context_settings_free(struct context_settings *settings)
|
||||
g_free(settings->ipv4->netmask);
|
||||
g_free(settings->ipv4->gateway);
|
||||
g_strfreev(settings->ipv4->dns);
|
||||
g_strfreev(settings->ipv4->pcscf);
|
||||
g_free(settings->ipv4->proxy);
|
||||
|
||||
g_free(settings->ipv4);
|
||||
@@ -420,6 +423,7 @@ static void context_settings_free(struct context_settings *settings)
|
||||
g_free(settings->ipv6->ip);
|
||||
g_free(settings->ipv6->gateway);
|
||||
g_strfreev(settings->ipv6->dns);
|
||||
g_strfreev(settings->ipv6->pcscf);
|
||||
|
||||
g_free(settings->ipv6);
|
||||
settings->ipv6 = NULL;
|
||||
@@ -484,6 +488,11 @@ static void context_settings_append_ipv4(struct context_settings *settings,
|
||||
DBUS_TYPE_STRING,
|
||||
&settings->ipv4->dns);
|
||||
|
||||
if (settings->ipv4->pcscf)
|
||||
ofono_dbus_dict_append_array(&array, "ProxyCSCF",
|
||||
DBUS_TYPE_STRING,
|
||||
&settings->ipv4->pcscf);
|
||||
|
||||
done:
|
||||
dbus_message_iter_close_container(&variant, &array);
|
||||
|
||||
@@ -549,6 +558,11 @@ static void context_settings_append_ipv6(struct context_settings *settings,
|
||||
DBUS_TYPE_STRING,
|
||||
&settings->ipv6->dns);
|
||||
|
||||
if (settings->ipv6->pcscf)
|
||||
ofono_dbus_dict_append_array(&array, "ProxyCSCF",
|
||||
DBUS_TYPE_STRING,
|
||||
&settings->ipv6->pcscf);
|
||||
|
||||
done:
|
||||
dbus_message_iter_close_container(&variant, &array);
|
||||
|
||||
@@ -3417,6 +3431,18 @@ void ofono_gprs_context_set_ipv4_dns_servers(struct ofono_gprs_context *gc,
|
||||
settings->ipv4->dns = g_strdupv((char **) dns);
|
||||
}
|
||||
|
||||
void ofono_gprs_context_set_ipv4_proxy_cscf(struct ofono_gprs_context *gc,
|
||||
const char **pcscf)
|
||||
{
|
||||
struct context_settings *settings = gc->settings;
|
||||
|
||||
if (settings->ipv4 == NULL)
|
||||
return;
|
||||
|
||||
g_strfreev(settings->ipv4->pcscf);
|
||||
settings->ipv4->pcscf = g_strdupv((char **) pcscf);
|
||||
}
|
||||
|
||||
void ofono_gprs_context_set_ipv6_address(struct ofono_gprs_context *gc,
|
||||
const char *address)
|
||||
{
|
||||
@@ -3464,6 +3490,18 @@ void ofono_gprs_context_set_ipv6_dns_servers(struct ofono_gprs_context *gc,
|
||||
settings->ipv6->dns = g_strdupv((char **) dns);
|
||||
}
|
||||
|
||||
void ofono_gprs_context_set_ipv6_proxy_cscf(struct ofono_gprs_context *gc,
|
||||
const char **pcscf)
|
||||
{
|
||||
struct context_settings *settings = gc->settings;
|
||||
|
||||
if (settings->ipv6 == NULL)
|
||||
return;
|
||||
|
||||
g_strfreev(settings->ipv6->pcscf);
|
||||
settings->ipv6->pcscf = g_strdupv((char **) pcscf);
|
||||
}
|
||||
|
||||
void ofono_gprs_context_signal_change(struct ofono_gprs_context *gc,
|
||||
unsigned int cid)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2020 Jolla Ltd.
|
||||
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
|
||||
*
|
||||
* 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
|
||||
@@ -281,7 +283,7 @@ int main(int argc, char **argv)
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, OFONO_SERVICE, &error);
|
||||
conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &error);
|
||||
if (conn == NULL) {
|
||||
if (dbus_error_is_set(&error) == TRUE) {
|
||||
ofono_error("Unable to hop onto D-Bus: %s",
|
||||
@@ -308,7 +310,12 @@ int main(int argc, char **argv)
|
||||
g_free(option_plugin);
|
||||
g_free(option_noplugin);
|
||||
|
||||
if (g_dbus_request_name(conn, OFONO_SERVICE, &error)) {
|
||||
g_main_loop_run(event_loop);
|
||||
} else {
|
||||
ofono_error("Unable to register D-Bus name: %s", error.message);
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
__ofono_plugin_cleanup();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2019 Jolla Ltd.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019 Open Mobile Platform LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -388,6 +388,7 @@ unsigned short __ofono_sms_get_next_ref(struct ofono_sms *sms);
|
||||
|
||||
#include <ofono/sim.h>
|
||||
|
||||
struct sim_aid;
|
||||
struct ofono_sim_aid_session;
|
||||
enum sim_app_type;
|
||||
|
||||
@@ -426,7 +427,7 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
unsigned int id);
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
|
||||
struct ofono_sim *sim, unsigned char *aid);
|
||||
struct ofono_sim *sim, const struct sim_aid *aid);
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
|
||||
struct ofono_sim *sim, enum sim_app_type type);
|
||||
@@ -436,7 +437,7 @@ int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session);
|
||||
enum sim_app_type __ofono_sim_session_get_type(
|
||||
struct ofono_sim_aid_session *session);
|
||||
|
||||
unsigned char *__ofono_sim_session_get_aid(
|
||||
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);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -62,7 +63,7 @@ struct auth_request {
|
||||
};
|
||||
|
||||
struct aid_object {
|
||||
uint8_t aid[16];
|
||||
struct sim_aid aid;
|
||||
char *path;
|
||||
enum sim_app_type type;
|
||||
};
|
||||
@@ -82,7 +83,7 @@ struct ofono_sim_auth {
|
||||
/*
|
||||
* Find an application by path. 'path' should be a DBusMessage object path.
|
||||
*/
|
||||
static uint8_t *find_aid_by_path(GSList *aid_objects,
|
||||
static const struct aid_object *find_aid_by_path(GSList *aid_objects,
|
||||
const char *path)
|
||||
{
|
||||
GSList *iter = aid_objects;
|
||||
@@ -91,7 +92,7 @@ static uint8_t *find_aid_by_path(GSList *aid_objects,
|
||||
struct aid_object *obj = iter->data;
|
||||
|
||||
if (!strcmp(path, obj->path))
|
||||
return obj->aid;
|
||||
return obj;
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
}
|
||||
@@ -208,14 +209,10 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
|
||||
DBusMessage *reply = NULL;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter dict;
|
||||
const uint8_t *res = NULL;
|
||||
const uint8_t *ck = NULL;
|
||||
const uint8_t *ik = NULL;
|
||||
const uint8_t *auts = NULL;
|
||||
const uint8_t *kc = NULL;
|
||||
struct data_block res, ck, ik, auts, sres, kc;
|
||||
|
||||
if (!sim_parse_umts_authenticate(resp, len, &res, &ck, &ik,
|
||||
&auts, &kc))
|
||||
&auts, &sres, &kc))
|
||||
goto umts_end;
|
||||
|
||||
reply = dbus_message_new_method_return(sa->pending->msg);
|
||||
@@ -225,15 +222,23 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
|
||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
||||
"{say}", &dict);
|
||||
|
||||
if (auts) {
|
||||
append_dict_byte_array(&dict, "AUTS", auts, 14);
|
||||
} else {
|
||||
append_dict_byte_array(&dict, "RES", res, 8);
|
||||
append_dict_byte_array(&dict, "CK", ck, 16);
|
||||
append_dict_byte_array(&dict, "IK", ik, 16);
|
||||
if (kc)
|
||||
append_dict_byte_array(&dict, "Kc", kc, 8);
|
||||
}
|
||||
if (auts.data)
|
||||
append_dict_byte_array(&dict, "AUTS", auts.data, auts.len);
|
||||
|
||||
if (sres.data)
|
||||
append_dict_byte_array(&dict, "SRES", sres.data, sres.len);
|
||||
|
||||
if (res.data)
|
||||
append_dict_byte_array(&dict, "RES", res.data, res.len);
|
||||
|
||||
if (ck.data)
|
||||
append_dict_byte_array(&dict, "CK", ck.data, ck.len);
|
||||
|
||||
if (ik.data)
|
||||
append_dict_byte_array(&dict, "IK", ik.data, ik.len);
|
||||
|
||||
if (kc.data)
|
||||
append_dict_byte_array(&dict, "Kc", kc.data, kc.len);
|
||||
|
||||
dbus_message_iter_close_container(&iter, &dict);
|
||||
|
||||
@@ -368,6 +373,8 @@ static void get_session_cb(ofono_bool_t active, int session_id,
|
||||
error:
|
||||
__ofono_dbus_pending_reply(&sa->pending->msg,
|
||||
__ofono_error_failed(sa->pending->msg));
|
||||
__ofono_sim_remove_session_watch(sa->pending->session,
|
||||
sa->pending->watch_id);
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
}
|
||||
@@ -378,7 +385,7 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
|
||||
struct ofono_sim_auth *sa = data;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter array;
|
||||
uint8_t *aid;
|
||||
const struct aid_object *obj;
|
||||
|
||||
if (sa->pending)
|
||||
return __ofono_error_busy(msg);
|
||||
@@ -418,12 +425,19 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
|
||||
/*
|
||||
* retrieve session from SIM
|
||||
*/
|
||||
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
|
||||
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
|
||||
&obj->aid);
|
||||
sa->pending->msg = dbus_message_ref(msg);
|
||||
sa->pending->watch_id = __ofono_sim_add_session_watch(
|
||||
sa->pending->session, get_session_cb, sa, NULL);
|
||||
|
||||
if (!sa->pending->watch_id) {
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
return __ofono_error_not_supported(msg);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
format_error:
|
||||
@@ -440,7 +454,7 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
|
||||
uint32_t rlen;
|
||||
uint32_t alen;
|
||||
struct ofono_sim_auth *sa = data;
|
||||
uint8_t *aid;
|
||||
const struct aid_object *obj;
|
||||
|
||||
if (sa->pending)
|
||||
return __ofono_error_busy(msg);
|
||||
@@ -465,12 +479,18 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
|
||||
/*
|
||||
* retrieve session from SIM
|
||||
*/
|
||||
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
|
||||
|
||||
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
|
||||
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
|
||||
&obj->aid);
|
||||
sa->pending->watch_id = __ofono_sim_add_session_watch(
|
||||
sa->pending->session, get_session_cb, sa, NULL);
|
||||
|
||||
if (!sa->pending->watch_id) {
|
||||
g_free(sa->pending);
|
||||
sa->pending = NULL;
|
||||
return __ofono_error_not_supported(msg);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -700,14 +720,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
|
||||
|
||||
ret = sprintf(new->path, "%s/", path);
|
||||
|
||||
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
|
||||
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
|
||||
new->path + ret);
|
||||
|
||||
g_dbus_register_interface(conn, new->path,
|
||||
OFONO_USIM_APPLICATION_INTERFACE,
|
||||
sim_auth_usim_app, NULL, NULL,
|
||||
sa, NULL);
|
||||
|
||||
memcpy(new->aid, r->aid, 16);
|
||||
new->aid = r->aid;
|
||||
|
||||
break;
|
||||
case SIM_APP_TYPE_ISIM:
|
||||
@@ -715,14 +736,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
|
||||
|
||||
ret = sprintf(new->path, "%s/", path);
|
||||
|
||||
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
|
||||
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
|
||||
new->path + ret);
|
||||
|
||||
g_dbus_register_interface(conn, new->path,
|
||||
OFONO_ISIM_APPLICATION_INTERFACE,
|
||||
sim_auth_isim_app, NULL, NULL,
|
||||
sa, NULL);
|
||||
|
||||
memcpy(new->aid, r->aid, 16);
|
||||
new->aid = r->aid;
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -2441,7 +2442,7 @@ struct ofono_sim_context *ofono_sim_context_create_isim(
|
||||
|
||||
if (session->record->type == SIM_APP_TYPE_ISIM) {
|
||||
return sim_fs_context_new_with_aid(sim->simfs_isim,
|
||||
session->record->aid);
|
||||
&session->record->aid);
|
||||
}
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
@@ -3667,6 +3668,26 @@ const char *__ofono_sim_get_impi(struct ofono_sim *sim)
|
||||
static void open_channel_cb(const struct ofono_error *error, int session_id,
|
||||
void *data);
|
||||
|
||||
static gboolean open_channel(struct ofono_sim_aid_session *session)
|
||||
{
|
||||
struct ofono_sim *sim = session->sim;
|
||||
const struct ofono_sim_driver *driver = sim->driver;
|
||||
const struct sim_aid *aid = &session->record->aid;
|
||||
|
||||
if (driver->open_channel2) {
|
||||
driver->open_channel2(sim, aid->aid, aid->len, open_channel_cb,
|
||||
session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (driver->open_channel && aid->len == 16) {
|
||||
driver->open_channel(sim, aid->aid, open_channel_cb, session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void close_channel_cb(const struct ofono_error *error, void *data)
|
||||
{
|
||||
struct ofono_sim_aid_session *session = data;
|
||||
@@ -3680,9 +3701,7 @@ static void close_channel_cb(const struct ofono_error *error, void *data)
|
||||
* An atom requested to open during a close, we can re-open
|
||||
* here.
|
||||
*/
|
||||
session->sim->driver->open_channel(session->sim,
|
||||
session->record->aid, open_channel_cb,
|
||||
session);
|
||||
if (open_channel(session))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3758,10 +3777,12 @@ unsigned int __ofono_sim_add_session_watch(
|
||||
* If the session is inactive and there are no watchers, open
|
||||
* a new session.
|
||||
*/
|
||||
if (open_channel(session)) {
|
||||
session->state = SESSION_STATE_OPENING;
|
||||
session->sim->driver->open_channel(session->sim,
|
||||
session->record->aid, open_channel_cb,
|
||||
session);
|
||||
} else {
|
||||
g_free(item);
|
||||
return 0;
|
||||
}
|
||||
} else if (session->state == SESSION_STATE_OPEN) {
|
||||
/*
|
||||
* Session is already open and available, just call the
|
||||
@@ -3784,7 +3805,8 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
{
|
||||
__ofono_watchlist_remove_item(session->watches, id);
|
||||
|
||||
if (g_slist_length(session->watches->items) == 0) {
|
||||
if (g_slist_length(session->watches->items) == 0 &&
|
||||
session->state == SESSION_STATE_OPEN) {
|
||||
/* last watcher, close session */
|
||||
session->state = SESSION_STATE_CLOSING;
|
||||
session->sim->driver->close_channel(session->sim,
|
||||
@@ -3793,14 +3815,15 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
|
||||
}
|
||||
|
||||
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
|
||||
struct ofono_sim *sim, unsigned char *aid)
|
||||
struct ofono_sim *sim, const struct sim_aid *aid)
|
||||
{
|
||||
GSList *iter = sim->aid_sessions;
|
||||
|
||||
while (iter) {
|
||||
struct ofono_sim_aid_session *session = iter->data;
|
||||
|
||||
if (!memcmp(session->record->aid, aid, 16))
|
||||
if (session->record->aid.len == aid->len &&
|
||||
!memcmp(session->record->aid.aid, aid->aid, aid->len))
|
||||
return session;
|
||||
|
||||
iter = g_slist_next(iter);
|
||||
@@ -3837,10 +3860,10 @@ enum sim_app_type __ofono_sim_session_get_type(
|
||||
return session->record->type;
|
||||
}
|
||||
|
||||
unsigned char *__ofono_sim_session_get_aid(
|
||||
const struct sim_aid *__ofono_sim_session_get_aid(
|
||||
struct ofono_sim_aid_session *session)
|
||||
{
|
||||
return session->record->aid;
|
||||
return &session->record->aid;
|
||||
}
|
||||
|
||||
GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -164,7 +165,7 @@ struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs)
|
||||
}
|
||||
|
||||
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
|
||||
unsigned char *aid)
|
||||
const struct sim_aid *aid)
|
||||
{
|
||||
struct ofono_sim_context *context = sim_fs_context_new(fs);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,6 +21,7 @@
|
||||
*/
|
||||
|
||||
struct sim_fs;
|
||||
struct sim_aid;
|
||||
|
||||
typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
|
||||
int total_length, int record_length,
|
||||
@@ -30,7 +32,7 @@ struct sim_fs *sim_fs_new(struct ofono_sim *sim,
|
||||
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
|
||||
|
||||
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
|
||||
unsigned char *aid);
|
||||
const struct sim_aid *aid);
|
||||
|
||||
unsigned int sim_fs_file_watch_add(struct ofono_sim_context *context,
|
||||
int id, ofono_sim_file_changed_cb_t cb,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -1419,7 +1420,7 @@ gboolean sim_parse_3g_get_response(const unsigned char *data, int len,
|
||||
if (tlv[1] != 0x21)
|
||||
return FALSE;
|
||||
|
||||
switch (tlv[0] & 0x3) {
|
||||
switch (tlv[0] & 0x7) {
|
||||
case 1: /* Transparent */
|
||||
str = 0x00;
|
||||
break;
|
||||
@@ -1572,20 +1573,17 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
|
||||
/* Find all the application entries */
|
||||
while ((dataobj = ber_tlv_find_by_tag(buffer, 0x61, len,
|
||||
&dataobj_len)) != NULL) {
|
||||
struct sim_app_record app;
|
||||
struct sim_app_record *app;
|
||||
const unsigned char *aid, *label;
|
||||
int label_len;
|
||||
int label_len, aid_len;
|
||||
char *app_label;
|
||||
|
||||
/* Find the aid (mandatory) */
|
||||
aid = ber_tlv_find_by_tag(dataobj, 0x4f, dataobj_len,
|
||||
&app.aid_len);
|
||||
if (!aid || app.aid_len < 0x01 || app.aid_len > 0x10)
|
||||
&aid_len);
|
||||
if (!aid || aid_len < 0x01 || aid_len > 0x10)
|
||||
goto error;
|
||||
|
||||
memcpy(app.aid, aid, app.aid_len);
|
||||
|
||||
app.type = (app.aid[5] << 8) | app.aid[6];
|
||||
|
||||
/* Find the label (optional) */
|
||||
label = ber_tlv_find_by_tag(dataobj, 0x50, dataobj_len,
|
||||
&label_len);
|
||||
@@ -1594,14 +1592,21 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
|
||||
* Label field uses the extra complicated
|
||||
* encoding in 102.221 Annex A
|
||||
*/
|
||||
app.label = sim_string_to_utf8(label, label_len);
|
||||
app_label = sim_string_to_utf8(label, label_len);
|
||||
|
||||
if (app.label == NULL)
|
||||
if (app_label == NULL)
|
||||
goto error;
|
||||
} else
|
||||
app.label = NULL;
|
||||
app_label = NULL;
|
||||
|
||||
ret = g_slist_prepend(ret, g_memdup(&app, sizeof(app)));
|
||||
app = g_new0(struct sim_app_record, 1);
|
||||
|
||||
memcpy(app->aid.aid, aid, aid_len);
|
||||
app->aid.len = aid_len;
|
||||
app->label = app_label;
|
||||
app->type = (aid[5] << 8) | aid[6];
|
||||
|
||||
ret = g_slist_prepend(ret, app);
|
||||
|
||||
len -= (dataobj - buffer) + dataobj_len;
|
||||
buffer = dataobj + dataobj_len;
|
||||
@@ -1667,67 +1672,135 @@ int sim_build_gsm_authenticate(unsigned char *buffer, int len,
|
||||
return build_authenticate(buffer, rand, NULL);
|
||||
}
|
||||
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
|
||||
int len, const unsigned char **res, const unsigned char **ck,
|
||||
const unsigned char **ik, const unsigned char **auts,
|
||||
const unsigned char **kc)
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
|
||||
struct data_block *res, struct data_block *ck,
|
||||
struct data_block *ik, struct data_block *auts,
|
||||
struct data_block *sres, struct data_block *kc)
|
||||
{
|
||||
if (len < 16 || !buffer)
|
||||
const unsigned char *ptr = buffer;
|
||||
const unsigned char *end = ptr + len;
|
||||
unsigned int l;
|
||||
|
||||
if (!buffer || len < 2)
|
||||
return FALSE;
|
||||
|
||||
switch (buffer[0]) {
|
||||
memset(res, 0, sizeof(*res));
|
||||
memset(ck, 0, sizeof(*ck));
|
||||
memset(ik, 0, sizeof(*ik));
|
||||
memset(kc, 0, sizeof(*kc));
|
||||
memset(auts, 0, sizeof(*auts));
|
||||
memset(sres, 0, sizeof(*sres));
|
||||
|
||||
/*
|
||||
* TS 31.102
|
||||
* 7.1.2.1 GSM/3G security context
|
||||
*/
|
||||
switch (*ptr++) {
|
||||
case 0xdb:
|
||||
/* 'DB' + '08' + RES(16) + '10' + CK(32) + '10' + IK(32) = 43 */
|
||||
if (len < 43)
|
||||
goto umts_end;
|
||||
/*
|
||||
* Response parameters/data, case 1, 3G security context,
|
||||
* command successful:
|
||||
*
|
||||
* "Successful 3G authentication" tag = 'DB'
|
||||
* 'DB' + L3 + RES(L3) + L4 + CK(L4) + L5 + IK(L5) + 8 + Kc(8)
|
||||
*/
|
||||
l = *ptr++; /* L3 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
/* success */
|
||||
if (buffer[1] != 0x08)
|
||||
goto umts_end;
|
||||
res->data = ptr;
|
||||
res->len = l;
|
||||
ptr += l;
|
||||
|
||||
*res = buffer + 2;
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
if (buffer[10] != 0x10)
|
||||
goto umts_end;
|
||||
l = *ptr++; /* L4 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
*ck = buffer + 11;
|
||||
ck->data = ptr;
|
||||
ck->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (buffer[27] != 0x10)
|
||||
goto umts_end;
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
*ik = buffer + 28;
|
||||
l = *ptr++; /* L5 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
if (len >= 53 && kc) {
|
||||
if (buffer[44] != 0x08)
|
||||
goto umts_end;
|
||||
ik->data = ptr;
|
||||
ik->len = l;
|
||||
ptr += l;
|
||||
|
||||
*kc = buffer + 45;
|
||||
} else {
|
||||
*kc = NULL;
|
||||
}
|
||||
if (ptr < end) {
|
||||
l = *ptr++;
|
||||
if (l != 8 || (ptr + l) != end)
|
||||
return FALSE;
|
||||
|
||||
*auts = NULL;
|
||||
|
||||
break;
|
||||
case 0xdc:
|
||||
/* 'DC' + '0E' + AUTS(14) = 16 */
|
||||
if (len < 16)
|
||||
goto umts_end;
|
||||
|
||||
/* sync error */
|
||||
if (buffer[1] != 0x0e)
|
||||
goto umts_end;
|
||||
|
||||
*auts = buffer + 2;
|
||||
|
||||
break;
|
||||
default:
|
||||
goto umts_end;
|
||||
kc->data = ptr;
|
||||
kc->len = l;
|
||||
ptr += l;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
umts_end:
|
||||
case 0xdc:
|
||||
/*
|
||||
* Response parameters/data, case 2, 3G security context,
|
||||
* synchronisation failure:
|
||||
*
|
||||
* "Synchronisation failure" tag = 'DC'
|
||||
* 'DC' + L1 + AUTS(L1)
|
||||
*/
|
||||
l = *ptr++; /* L1 */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
auts->data = ptr;
|
||||
auts->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (ptr != end)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 0x04:
|
||||
/*
|
||||
* Response parameters/data, case 3, GSM security context,
|
||||
* command successful:
|
||||
*
|
||||
* 4 + SRES(4) + 8 + Kc(8)
|
||||
*/
|
||||
l = 4; /* Already skipped this one */
|
||||
if ((ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
sres->data = ptr;
|
||||
sres->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (ptr == end)
|
||||
return FALSE;
|
||||
|
||||
l = *ptr++; /* 8 */
|
||||
if (l != 8 || (ptr + l) > end)
|
||||
return FALSE;
|
||||
|
||||
kc->data = ptr;
|
||||
kc->len = l;
|
||||
ptr += l;
|
||||
|
||||
if (ptr != end)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,9 +314,13 @@ struct sim_ef_info {
|
||||
enum sim_file_access perm_update;
|
||||
};
|
||||
|
||||
struct sim_app_record {
|
||||
struct sim_aid {
|
||||
unsigned char aid[16];
|
||||
int aid_len;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
struct sim_app_record {
|
||||
struct sim_aid aid;
|
||||
char *label;
|
||||
enum sim_app_type type;
|
||||
};
|
||||
@@ -371,6 +375,11 @@ struct comprehension_tlv_builder {
|
||||
struct ber_tlv_builder *parent;
|
||||
};
|
||||
|
||||
struct data_block {
|
||||
const unsigned char *data;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
void simple_tlv_iter_init(struct simple_tlv_iter *iter,
|
||||
const unsigned char *pdu, unsigned int len);
|
||||
gboolean simple_tlv_iter_next(struct simple_tlv_iter *iter);
|
||||
@@ -526,10 +535,10 @@ int sim_build_umts_authenticate(unsigned char *buffer, int len,
|
||||
int sim_build_gsm_authenticate(unsigned char *buffer, int len,
|
||||
const unsigned char *rand);
|
||||
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
|
||||
int len, const unsigned char **res, const unsigned char **ck,
|
||||
const unsigned char **ik, const unsigned char **auts,
|
||||
const unsigned char **kc);
|
||||
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
|
||||
struct data_block *res, struct data_block *ck,
|
||||
struct data_block *ik, struct data_block *auts,
|
||||
struct data_block *sres, struct data_block *kc);
|
||||
|
||||
gboolean sim_parse_gsm_authenticate(const unsigned char *buffer, int len,
|
||||
const unsigned char **sres, const unsigned char **kc);
|
||||
|
||||
@@ -417,7 +417,7 @@ static void test_reply_last_reply(DBusPendingCall *call, void *dbus)
|
||||
G_CAST(dbus, struct test_reply_data, dbus);
|
||||
|
||||
DBG("");
|
||||
test_dbus_check_error_reply(call, TEST_ERROR_FAILED);
|
||||
test_dbus_check_empty_reply(call, NULL);
|
||||
g_main_loop_quit(test->dbus.loop);
|
||||
}
|
||||
|
||||
@@ -445,6 +445,12 @@ static DBusMessage *test_reply_4(DBusMessage *msg, void *data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *test_reply_5(DBusMessage *msg, void *data)
|
||||
{
|
||||
DBG("");
|
||||
return dbus_message_new_method_return(msg);
|
||||
}
|
||||
|
||||
static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -485,10 +491,17 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
case 6:
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_4,
|
||||
msg, NULL);
|
||||
break;
|
||||
case 7:
|
||||
/* Call the same method again */
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_4,
|
||||
msg, NULL);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
/* Call the last one */
|
||||
__ofono_dbus_queue_request(test->queue, test_reply_5,
|
||||
msg, NULL);
|
||||
|
||||
/* This completes the first one, with NULL handler */
|
||||
__ofono_dbus_queue_reply_all_fn_param(test->queue, NULL, NULL);
|
||||
g_assert(__ofono_dbus_queue_pending(test->queue));
|
||||
@@ -508,10 +521,12 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
|
||||
/* This one test_reply_3 with Failed */
|
||||
__ofono_dbus_queue_reply_all_error(test->queue, NULL);
|
||||
|
||||
/* This one test_reply_4 with NotSupported */
|
||||
/* This one completes all test_reply_4 with NotSupported */
|
||||
error.type = OFONO_ERROR_TYPE_ERRNO;
|
||||
error.error = -EOPNOTSUPP;
|
||||
__ofono_dbus_queue_reply_all_error(test->queue, &error);
|
||||
|
||||
/* test_reply_5 must be already completed */
|
||||
g_assert(!__ofono_dbus_queue_pending(test->queue));
|
||||
|
||||
/* And this one does nothing */
|
||||
@@ -541,7 +556,8 @@ static void test_reply_start(struct test_dbus_context *dbus)
|
||||
test_client_call(dbus, 4, test_dbus_expect_empty_reply);
|
||||
test_client_call(dbus, 5, test_expect_failed);
|
||||
test_client_call(dbus, 6, test_expect_not_supported);
|
||||
test_client_call(dbus, 7, test_reply_last_reply);
|
||||
test_client_call(dbus, 7, test_expect_not_supported);
|
||||
test_client_call(dbus, 8, test_reply_last_reply);
|
||||
}
|
||||
|
||||
static void test_reply(void)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -491,12 +492,12 @@ static void test_application_entry_decode(void)
|
||||
app[0] = entries->next->data;
|
||||
app[1] = entries->data;
|
||||
|
||||
g_assert(app[0]->aid_len == 0x10);
|
||||
g_assert(!memcmp(app[0]->aid, &ef_dir[4], 0x10));
|
||||
g_assert(app[0]->aid.len == 0x10);
|
||||
g_assert(!memcmp(app[0]->aid.aid, &ef_dir[4], 0x10));
|
||||
g_assert(app[0]->label == NULL);
|
||||
|
||||
g_assert(app[1]->aid_len == 0x0c);
|
||||
g_assert(!memcmp(app[1]->aid, &ef_dir[37], 0x0c));
|
||||
g_assert(app[1]->aid.len == 0x0c);
|
||||
g_assert(!memcmp(app[1]->aid.aid, &ef_dir[37], 0x0c));
|
||||
g_assert(app[1]->label != NULL);
|
||||
g_assert(!strcmp(app[1]->label, "MIDPfiles"));
|
||||
|
||||
@@ -529,32 +530,34 @@ static void test_get_2g_path(void)
|
||||
static void test_auth_build_parse(void)
|
||||
{
|
||||
unsigned char auth_cmd[40];
|
||||
const unsigned char rand[16] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
|
||||
const unsigned char rand[] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
|
||||
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0e, 0x0f };
|
||||
const unsigned char sres[4] = { 0x00, 0x11, 0x22, 0x33 };
|
||||
const unsigned char sres[] = { 0x00, 0x11, 0x22, 0x33 };
|
||||
const unsigned char *sres_p;
|
||||
struct data_block sres_b;
|
||||
const unsigned char kc[8] = { 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56,
|
||||
0x78, 0x9a };
|
||||
const unsigned char *kc_p;
|
||||
struct data_block kc_b;
|
||||
const unsigned char gsm_success[] = { 0x04, 0x00, 0x11, 0x22, 0x33,
|
||||
0x08,0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
|
||||
const unsigned char autn[16] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
const unsigned char autn[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
|
||||
0x01, 0x00 };
|
||||
const unsigned char res[8] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
|
||||
const unsigned char res[] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
|
||||
0x11, 0x22 };
|
||||
const unsigned char *res_p;
|
||||
const unsigned char ck[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
struct data_block res_b;
|
||||
const unsigned char ck[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
const unsigned char *ck_p;
|
||||
const unsigned char ik[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
struct data_block ck_b;
|
||||
const unsigned char ik[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||
const unsigned char *ik_p;
|
||||
const unsigned char auts[16] = { 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
|
||||
0xbe, 0xef };
|
||||
const unsigned char *auts_p;
|
||||
struct data_block ik_b;
|
||||
const unsigned char auts[] = { 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
|
||||
0xef, 0xde, 0xea };
|
||||
struct data_block auts_b;
|
||||
|
||||
const unsigned char umts_success[] = { 0xdb, 0x08, 0xff, 0xee, 0xdd,
|
||||
0xcc, 0xbb, 0xaa, 0x11, 0x22, 0x10, 0x00, 0x11, 0x22,
|
||||
@@ -572,6 +575,8 @@ static void test_auth_build_parse(void)
|
||||
const unsigned char umts_sync_failure[] = { 0xdc, 0x0e, 0xde, 0xea,
|
||||
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
|
||||
0xef, 0xde, 0xea };
|
||||
const unsigned char case3[] = { 0x04, 0x01, 0x02, 0x03, 0x04,
|
||||
0x08, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
|
||||
int len = 0;
|
||||
|
||||
/* test GSM auth command */
|
||||
@@ -606,31 +611,96 @@ static void test_auth_build_parse(void)
|
||||
g_assert(!memcmp(sres_p, sres, 4));
|
||||
g_assert(!memcmp(kc_p, kc, 8));
|
||||
|
||||
/* test truncated messages */
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 10,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 11,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 27,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success, 28,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_sync_failure, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 2,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 5,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, 6,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* the extra byte won't actually be accessed */
|
||||
g_assert(!sim_parse_umts_authenticate(umts_success,
|
||||
sizeof(umts_success) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(umts_sync_failure,
|
||||
sizeof(umts_sync_failure) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert(!sim_parse_umts_authenticate(case3, sizeof(case3) + 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* unrecognized data */
|
||||
g_assert(!sim_parse_umts_authenticate(case3 + 1, sizeof(case3) - 1,
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
|
||||
/* test UMTS success parse, no kc */
|
||||
g_assert(sim_parse_umts_authenticate(umts_success, sizeof(umts_success),
|
||||
&res_p, &ck_p, &ik_p, &auts_p, &kc_p));
|
||||
g_assert(!memcmp(res_p, res, 8));
|
||||
g_assert(!memcmp(ck_p, ck, 16));
|
||||
g_assert(!memcmp(ik_p, ik, 16));
|
||||
g_assert(!auts_p && !kc_p);
|
||||
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
|
||||
g_assert_cmpuint(res_b.len, == , sizeof(res));
|
||||
g_assert(!memcmp(res_b.data, res, sizeof(res)));
|
||||
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
|
||||
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
|
||||
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
|
||||
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
g_assert(!kc_b.len && !kc_b.data);
|
||||
|
||||
/* test UMTS sync failure */
|
||||
g_assert(sim_parse_umts_authenticate(umts_sync_failure,
|
||||
sizeof(umts_sync_failure),
|
||||
&res_p, &ck_p, &ik_p, &auts_p,
|
||||
&kc_p));
|
||||
g_assert(!memcmp(auts_p, auts, 14));
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert_cmpuint(auts_b.len, == , sizeof(auts));
|
||||
g_assert(!memcmp(auts_b.data, auts, sizeof(auts)));
|
||||
g_assert(!res_b.len && !res_b.data);
|
||||
g_assert(!ck_b.len && !ck_b.data);
|
||||
g_assert(!ik_b.len && !ik_b.data);
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!kc_b.len && !kc_b.data);
|
||||
|
||||
/* test UMTS success parse, with kc */
|
||||
g_assert(sim_parse_umts_authenticate(umts_success_kc,
|
||||
sizeof(umts_success_kc),
|
||||
&res_p, &ck_p, &ik_p, &auts_p,
|
||||
&kc_p));
|
||||
g_assert(!memcmp(res_p, res, 8));
|
||||
g_assert(!memcmp(ck_p, ck, 16));
|
||||
g_assert(!memcmp(ik_p, ik, 16));
|
||||
g_assert(!memcmp(kc_p, kc, 8));
|
||||
g_assert(!auts_p);
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert_cmpuint(res_b.len, == , sizeof(res));
|
||||
g_assert(!memcmp(res_b.data, res, sizeof(res)));
|
||||
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
|
||||
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
|
||||
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
|
||||
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
|
||||
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
|
||||
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
|
||||
g_assert(!sres_b.len && !sres_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
|
||||
/* test case3 */
|
||||
g_assert(sim_parse_umts_authenticate(case3, sizeof(case3),
|
||||
&res_b, &ck_b, &ik_b, &auts_b,
|
||||
&sres_b, &kc_b));
|
||||
g_assert(!res_b.len && !res_b.data);
|
||||
g_assert(!ck_b.len && !ck_b.data);
|
||||
g_assert(!ik_b.len && !ik_b.data);
|
||||
g_assert(!auts_b.len && !auts_b.data);
|
||||
g_assert_cmpuint(sres_b.len, == , 4);
|
||||
g_assert(!memcmp(sres_b.data, case3 + 1, sres_b.len));
|
||||
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
|
||||
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
Reference in New Issue
Block a user