mirror of git://git.sysmocom.de/ofono
call-forwarding: Read/Write cfis/cphs-cff
This commit is contained in:
parent
49ae1f919a
commit
8f8ae1b62f
|
@ -34,6 +34,7 @@
|
|||
#include "ofono.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "simutil.h"
|
||||
|
||||
#define CALL_FORWARDING_FLAG_CACHED 0x1
|
||||
|
||||
|
@ -58,6 +59,11 @@ struct ofono_call_forwarding {
|
|||
int query_next;
|
||||
int query_end;
|
||||
struct cf_ss_request *ss_req;
|
||||
struct ofono_sim *sim;
|
||||
unsigned char cfis_record_id;
|
||||
unsigned char cfis_indicator;
|
||||
ofono_bool_t cphs_cff_present;
|
||||
ofono_bool_t status_on_sim;
|
||||
struct ofono_ussd *ussd;
|
||||
unsigned int ussd_watch;
|
||||
const struct ofono_call_forwarding_driver *driver;
|
||||
|
@ -202,6 +208,83 @@ static const char *cf_type_lut[] = {
|
|||
"AllConditional"
|
||||
};
|
||||
|
||||
static void sim_cfis_update_cb(int ok, void *data)
|
||||
{
|
||||
if (!ok)
|
||||
ofono_info("Failed to update EFcfis");
|
||||
}
|
||||
|
||||
static void sim_cphs_cff_update_cb(int ok, void *data)
|
||||
{
|
||||
if (!ok)
|
||||
ofono_info("Failed to update EFcphs-cff");
|
||||
}
|
||||
|
||||
static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
|
||||
{
|
||||
gboolean cfu_voice = FALSE;
|
||||
struct ofono_call_forwarding_condition *cond = NULL;
|
||||
GSList *l;
|
||||
const char *number = NULL;
|
||||
|
||||
/*
|
||||
* For now we only support Voice, although Fax & all Data
|
||||
* basic services are applicable as well.
|
||||
*/
|
||||
for (l = cf->cf_conditions[0]; l; l = l->next) {
|
||||
cond = l->data;
|
||||
|
||||
if ((cond->cls & BEARER_CLASS_VOICE) &&
|
||||
(strlen(cond->phone_number.number) > 0)) {
|
||||
number = phone_number_to_string(&cond->phone_number);
|
||||
cfu_voice = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cf->status_on_sim = cfu_voice;
|
||||
|
||||
if (cf->cfis_record_id) {
|
||||
unsigned char data[16];
|
||||
int number_len;
|
||||
|
||||
memset(data, 0xff, sizeof(data));
|
||||
|
||||
/* Profile Identifier */
|
||||
data[0] = 0x01;
|
||||
|
||||
if (cfu_voice) {
|
||||
number_len = strlen(cond->phone_number.number);
|
||||
|
||||
/* CFU indicator Status - Voice */
|
||||
data[1] = (cf->cfis_indicator |= 0x01);
|
||||
number_len = (number_len + 1) / 2;
|
||||
data[2] = number_len + 1;
|
||||
data[3] = cond->phone_number.type;
|
||||
|
||||
sim_encode_bcd_number(cond->phone_number.number,
|
||||
data + 4);
|
||||
} else
|
||||
data[1] = (cf->cfis_indicator &= 0xFE);
|
||||
|
||||
ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
|
||||
sim_cfis_update_cb,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
cf->cfis_record_id, data,
|
||||
sizeof(data), cf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cf->cphs_cff_present) {
|
||||
unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
|
||||
|
||||
ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
|
||||
sim_cphs_cff_update_cb,
|
||||
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
||||
0, &cff_voice, sizeof(cff_voice), cf);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
||||
int type, GSList *list)
|
||||
{
|
||||
|
@ -216,6 +299,7 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
|||
dbus_uint16_t timeout;
|
||||
char attr[64];
|
||||
char tattr[64];
|
||||
gboolean update_sim = FALSE;
|
||||
|
||||
for (l = list; l; l = l->next) {
|
||||
lc = l->data;
|
||||
|
@ -246,12 +330,16 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
|||
|
||||
if (oc->phone_number.type != lc->phone_number.type ||
|
||||
strcmp(oc->phone_number.number,
|
||||
lc->phone_number.number))
|
||||
lc->phone_number.number)) {
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
OFONO_CALL_FORWARDING_INTERFACE,
|
||||
attr, DBUS_TYPE_STRING,
|
||||
&number);
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
|
||||
update_sim = TRUE;
|
||||
}
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
|
||||
oc->time != lc->time)
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
|
@ -270,6 +358,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
|||
attr, DBUS_TYPE_STRING,
|
||||
&number);
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
|
||||
update_sim = TRUE;
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
|
||||
lc->time != DEFAULT_NO_REPLY_TIMEOUT)
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
|
@ -302,6 +393,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
|||
OFONO_CALL_FORWARDING_INTERFACE, attr,
|
||||
DBUS_TYPE_STRING, &number);
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
|
||||
update_sim = TRUE;
|
||||
|
||||
if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
|
||||
oc->time != DEFAULT_NO_REPLY_TIMEOUT)
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
|
@ -312,6 +406,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
|
|||
|
||||
cf_list_clear(old);
|
||||
cf->cf_conditions[type] = list;
|
||||
|
||||
if (update_sim == TRUE)
|
||||
sim_set_cf_indicator(cf);
|
||||
}
|
||||
|
||||
static inline void property_append_cf_condition(DBusMessageIter *dict, int cls,
|
||||
|
@ -372,6 +469,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
|
|||
DBusMessageIter iter;
|
||||
DBusMessageIter dict;
|
||||
int i;
|
||||
dbus_bool_t status;
|
||||
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
if (reply == NULL)
|
||||
|
@ -388,6 +486,10 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
|
|||
BEARER_CLASS_VOICE,
|
||||
cf_type_lut[i]);
|
||||
|
||||
status = cf->status_on_sim;
|
||||
ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
|
||||
&status);
|
||||
|
||||
dbus_message_iter_close_container(&iter, &dict);
|
||||
|
||||
return reply;
|
||||
|
@ -431,8 +533,10 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
|
|||
void *data)
|
||||
{
|
||||
struct ofono_call_forwarding *cf = data;
|
||||
struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
|
||||
|
||||
if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
|
||||
if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
|
||||
ofono_modem_get_online(modem) == FALSE)
|
||||
return cf_get_properties_reply(msg, cf);
|
||||
|
||||
if (cf->driver->query == NULL)
|
||||
|
@ -590,12 +694,16 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
|
|||
void *data)
|
||||
{
|
||||
struct ofono_call_forwarding *cf = data;
|
||||
struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter var;
|
||||
const char *property;
|
||||
int cls;
|
||||
int type;
|
||||
|
||||
if (ofono_modem_get_online(modem) == FALSE)
|
||||
return __ofono_error_not_available(msg);
|
||||
|
||||
if (__ofono_call_forwarding_is_busy(cf) ||
|
||||
__ofono_ussd_is_busy(cf->ussd))
|
||||
return __ofono_error_busy(msg);
|
||||
|
@ -1111,6 +1219,128 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
|
|||
return cf->pending ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void sim_cfis_read_cb(int ok, int total_length, int record,
|
||||
const unsigned char *data,
|
||||
int record_length, void *userdata)
|
||||
{
|
||||
struct ofono_call_forwarding *cf = userdata;
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
const char *path = __ofono_atom_get_path(cf->atom);
|
||||
|
||||
if (!ok || record_length < 16 || total_length < record_length) {
|
||||
cf->cfis_indicator = 0;
|
||||
cf->cfis_record_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiple Subscriber Profile number which can have values 1-4.
|
||||
* Profile id 1 is assumed as the current profile.
|
||||
*/
|
||||
if (data[0] != 1)
|
||||
return;
|
||||
|
||||
cf->cfis_record_id = record;
|
||||
|
||||
/* CFU indicator status */
|
||||
cf->cfis_indicator = data[1];
|
||||
|
||||
/*
|
||||
* For now we only support Voice, although Fax & all Data
|
||||
* basic services are applicable as well.
|
||||
*/
|
||||
if (cf->cfis_indicator & 0x01) {
|
||||
int ton_npi;
|
||||
int number_len;
|
||||
const char *number;
|
||||
char attr[64];
|
||||
struct ofono_call_forwarding_condition *cond;
|
||||
GSList *l = NULL;
|
||||
dbus_bool_t status;
|
||||
|
||||
number_len = data[2];
|
||||
ton_npi = data[3];
|
||||
|
||||
if (number_len > 11 || ton_npi == 0xff)
|
||||
return;
|
||||
|
||||
cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
|
||||
if (cond == NULL)
|
||||
return;
|
||||
|
||||
status = cf->status_on_sim = TRUE;
|
||||
cond->status = status;
|
||||
cond->cls = BEARER_CLASS_VOICE;
|
||||
cond->time = 0;
|
||||
cond->phone_number.type = ton_npi;
|
||||
|
||||
sim_extract_bcd_number(data + 4, number_len - 1,
|
||||
cond->phone_number.number);
|
||||
number = phone_number_to_string(&cond->phone_number);
|
||||
|
||||
snprintf(attr, sizeof(attr), "%s%s",
|
||||
bearer_class_to_string(BEARER_CLASS_VOICE),
|
||||
cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
|
||||
|
||||
cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
|
||||
g_slist_append(l, cond);
|
||||
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
OFONO_CALL_FORWARDING_INTERFACE,
|
||||
attr, DBUS_TYPE_STRING,
|
||||
&number);
|
||||
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
OFONO_CALL_FORWARDING_INTERFACE,
|
||||
"ForwardingFlagOnSim",
|
||||
DBUS_TYPE_BOOLEAN,
|
||||
&status);
|
||||
}
|
||||
}
|
||||
|
||||
static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
|
||||
const unsigned char *data,
|
||||
int record_length, void *userdata)
|
||||
{
|
||||
struct ofono_call_forwarding *cf = userdata;
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
const char *path = __ofono_atom_get_path(cf->atom);
|
||||
dbus_bool_t cfu_voice;
|
||||
|
||||
if (!ok || total_length < 1) {
|
||||
cf->cphs_cff_present = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
cf->cphs_cff_present = TRUE;
|
||||
|
||||
/*
|
||||
* For now we only support Voice, although Fax & all Data
|
||||
* basic services are applicable as well.
|
||||
*/
|
||||
cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
|
||||
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
OFONO_CALL_FORWARDING_INTERFACE,
|
||||
"ForwardingFlagOnSim",
|
||||
DBUS_TYPE_BOOLEAN,
|
||||
&cfu_voice);
|
||||
}
|
||||
|
||||
static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
|
||||
{
|
||||
if (__ofono_sim_service_available(cf->sim,
|
||||
SIM_UST_SERVICE_CFIS,
|
||||
SIM_SST_SERVICE_CFIS) == TRUE)
|
||||
ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
sim_cfis_read_cb, cf);
|
||||
else
|
||||
ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
||||
sim_cphs_cff_read_cb, cf);
|
||||
}
|
||||
|
||||
int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
|
||||
{
|
||||
DBG("driver: %p, name: %s", d, d->name);
|
||||
|
@ -1219,6 +1449,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
|
|||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
const char *path = __ofono_atom_get_path(cf->atom);
|
||||
struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
|
||||
struct ofono_atom *sim_atom;
|
||||
struct ofono_atom *ussd_atom;
|
||||
|
||||
if (!g_dbus_register_interface(conn, path,
|
||||
|
@ -1233,6 +1464,14 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
|
|||
|
||||
ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
|
||||
|
||||
sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
|
||||
|
||||
if (sim_atom) {
|
||||
cf->sim = __ofono_atom_get_data(sim_atom);
|
||||
|
||||
sim_read_cf_indicator(cf);
|
||||
}
|
||||
|
||||
cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
|
||||
OFONO_ATOM_TYPE_USSD,
|
||||
ussd_watch, cf, NULL);
|
||||
|
|
Loading…
Reference in New Issue