mirror of
https://github.com/sailfishos/ofono
synced 2025-11-29 06:01:05 +08:00
Compare commits
14 Commits
mer/1.18+g
...
mer/1.18+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2520664c63 | ||
|
|
445bbbd66f | ||
|
|
08fc4b0d03 | ||
|
|
c82e94ffb4 | ||
|
|
fd3712940b | ||
|
|
8410c985c9 | ||
|
|
0878decdc0 | ||
|
|
cb69984722 | ||
|
|
1fe8701f1a | ||
|
|
c5286fee70 | ||
|
|
3c5f6f84e1 | ||
|
|
8b87b55e8d | ||
|
|
bce34cbff3 | ||
|
|
f8351cacf1 |
@@ -100,6 +100,7 @@ struct ril_data_priv {
|
|||||||
struct ril_data_request *pending_req;
|
struct ril_data_request *pending_req;
|
||||||
|
|
||||||
enum ril_data_allow_data_opt allow_data;
|
enum ril_data_allow_data_opt allow_data;
|
||||||
|
enum ril_data_call_format data_call_format;
|
||||||
char *log_prefix;
|
char *log_prefix;
|
||||||
guint query_id;
|
guint query_id;
|
||||||
gulong io_event_id;
|
gulong io_event_id;
|
||||||
@@ -172,7 +173,6 @@ struct ril_data_request_2g {
|
|||||||
gulong handler_id;
|
gulong handler_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean ril_data_manager_handover(struct ril_data_manager *dm);
|
|
||||||
static void ril_data_manager_check_data(struct ril_data_manager *dm);
|
static void ril_data_manager_check_data(struct ril_data_manager *dm);
|
||||||
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);
|
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);
|
||||||
|
|
||||||
@@ -272,7 +272,8 @@ static int ril_data_protocol_to_ofono(gchar *str)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp)
|
static struct ril_data_call *ril_data_call_parse(int version,
|
||||||
|
GRilIoParser *rilp)
|
||||||
{
|
{
|
||||||
int prot;
|
int prot;
|
||||||
char *prot_str;
|
char *prot_str;
|
||||||
@@ -280,6 +281,7 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
|
|||||||
guint32 active = RIL_DATA_CALL_INACTIVE;
|
guint32 active = RIL_DATA_CALL_INACTIVE;
|
||||||
struct ril_data_call *call = g_new0(struct ril_data_call, 1);
|
struct ril_data_call *call = g_new0(struct ril_data_call, 1);
|
||||||
|
|
||||||
|
/* RIL_Data_Call_Response_v6 (see ril.h) */
|
||||||
grilio_parser_get_uint32(rilp, &status);
|
grilio_parser_get_uint32(rilp, &status);
|
||||||
grilio_parser_get_int32(rilp, &call->retry_time);
|
grilio_parser_get_int32(rilp, &call->retry_time);
|
||||||
grilio_parser_get_int32(rilp, &call->cid);
|
grilio_parser_get_int32(rilp, &call->cid);
|
||||||
@@ -299,15 +301,13 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
|
|||||||
call->status = status;
|
call->status = status;
|
||||||
call->active = active;
|
call->active = active;
|
||||||
|
|
||||||
|
/* RIL_Data_Call_Response_v9 */
|
||||||
if (version >= 9) {
|
if (version >= 9) {
|
||||||
/* PCSCF */
|
/* PCSCF */
|
||||||
grilio_parser_skip_string(rilp);
|
grilio_parser_skip_string(rilp);
|
||||||
|
|
||||||
/*
|
/* RIL_Data_Call_Response_v11 */
|
||||||
* All known rils that report version 10 are using
|
if (version >= 11) {
|
||||||
* RIL_Data_Call_Response_v11 (FairPhone 2, Nexus 4)
|
|
||||||
*/
|
|
||||||
if (version >= 10) {
|
|
||||||
/* MTU */
|
/* MTU */
|
||||||
grilio_parser_get_int32(rilp, &call->mtu);
|
grilio_parser_get_int32(rilp, &call->mtu);
|
||||||
}
|
}
|
||||||
@@ -317,7 +317,8 @@ static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp
|
|||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_data_call_list *ril_data_call_list_parse(const void *data, guint len)
|
static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
|
||||||
|
guint len, enum ril_data_call_format format)
|
||||||
{
|
{
|
||||||
unsigned int version, n, i;
|
unsigned int version, n, i;
|
||||||
GRilIoParser rilp;
|
GRilIoParser rilp;
|
||||||
@@ -328,8 +329,13 @@ struct ril_data_call_list *ril_data_call_list_parse(const void *data, guint len)
|
|||||||
struct ril_data_call_list *list =
|
struct ril_data_call_list *list =
|
||||||
g_new0(struct ril_data_call_list, 1);
|
g_new0(struct ril_data_call_list, 1);
|
||||||
|
|
||||||
DBG("version=%u,num=%u", version, n);
|
if (format == RIL_DATA_CALL_FORMAT_AUTO || format == version) {
|
||||||
list->version = version;
|
DBG("version=%u,num=%u", version, n);
|
||||||
|
list->version = version;
|
||||||
|
} else {
|
||||||
|
DBG("version=%u(%d),num=%u", version, format, n);
|
||||||
|
list->version = format;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
|
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
|
||||||
struct ril_data_call *call =
|
struct ril_data_call *call =
|
||||||
@@ -499,7 +505,8 @@ static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
|
|||||||
priv->query_id = 0;
|
priv->query_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
|
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||||
|
priv->data_call_format));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
||||||
@@ -511,7 +518,8 @@ static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
|||||||
GASSERT(priv->query_id);
|
GASSERT(priv->query_id);
|
||||||
priv->query_id = 0;
|
priv->query_id = 0;
|
||||||
if (ril_status == RIL_E_SUCCESS) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
|
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||||
|
priv->data_call_format));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,11 +594,11 @@ static gboolean ril_data_request_do_cancel(struct ril_data_request *req)
|
|||||||
struct ril_data_priv *priv = req->data->priv;
|
struct ril_data_priv *priv = req->data->priv;
|
||||||
|
|
||||||
DBG_(req->data, "canceling %s request %p", req->name, req);
|
DBG_(req->data, "canceling %s request %p", req->name, req);
|
||||||
|
if (req->cancel) {
|
||||||
|
req->cancel(req);
|
||||||
|
}
|
||||||
if (priv->pending_req == req) {
|
if (priv->pending_req == req) {
|
||||||
/* Request has been submitted already */
|
/* Request has been submitted already */
|
||||||
if (req->cancel) {
|
|
||||||
req->cancel(req);
|
|
||||||
}
|
|
||||||
priv->pending_req = NULL;
|
priv->pending_req = NULL;
|
||||||
} else if (priv->req_queue == req) {
|
} else if (priv->req_queue == req) {
|
||||||
/* It's the first one in the queue */
|
/* It's the first one in the queue */
|
||||||
@@ -673,14 +681,11 @@ static void ril_data_request_queue(struct ril_data_request *req)
|
|||||||
|
|
||||||
static void ril_data_call_setup_cancel(struct ril_data_request *req)
|
static void ril_data_call_setup_cancel(struct ril_data_request *req)
|
||||||
{
|
{
|
||||||
if (req->pending_id) {
|
ril_data_request_cancel_io(req);
|
||||||
grilio_queue_cancel_request(req->data->priv->q,
|
if (req->cb.setup) {
|
||||||
req->pending_id, FALSE);
|
ril_data_call_setup_cb_t cb = req->cb.setup;
|
||||||
req->pending_id = 0;
|
req->cb.setup = NULL;
|
||||||
if (req->cb.setup) {
|
cb(req->data, GRILIO_STATUS_CANCELLED, NULL, req->arg);
|
||||||
req->cb.setup(req->data, GRILIO_STATUS_CANCELLED,
|
|
||||||
NULL, req->arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,11 +695,13 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
|||||||
struct ril_data_request_setup *setup = user_data;
|
struct ril_data_request_setup *setup = user_data;
|
||||||
struct ril_data_request *req = &setup->req;
|
struct ril_data_request *req = &setup->req;
|
||||||
struct ril_data *self = req->data;
|
struct ril_data *self = req->data;
|
||||||
|
struct ril_data_priv *priv = self->priv;
|
||||||
struct ril_data_call_list *list = NULL;
|
struct ril_data_call_list *list = NULL;
|
||||||
struct ril_data_call *call = NULL;
|
struct ril_data_call *call = NULL;
|
||||||
|
|
||||||
if (ril_status == RIL_E_SUCCESS) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
list = ril_data_call_list_parse(data, len);
|
list = ril_data_call_list_parse(data, len,
|
||||||
|
priv->data_call_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list) {
|
if (list) {
|
||||||
@@ -844,14 +851,11 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
|
|||||||
|
|
||||||
static void ril_data_call_deact_cancel(struct ril_data_request *req)
|
static void ril_data_call_deact_cancel(struct ril_data_request *req)
|
||||||
{
|
{
|
||||||
if (req->pending_id) {
|
ril_data_request_cancel_io(req);
|
||||||
grilio_queue_cancel_request(req->data->priv->q,
|
if (req->cb.deact) {
|
||||||
req->pending_id, FALSE);
|
ril_data_call_deactivate_cb_t cb = req->cb.deact;
|
||||||
req->pending_id = 0;
|
req->cb.deact = NULL;
|
||||||
if (req->cb.setup) {
|
cb(req->data, GRILIO_STATUS_CANCELLED, req->arg);
|
||||||
req->cb.deact(req->data, GRILIO_STATUS_CANCELLED,
|
|
||||||
req->arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,8 +1028,9 @@ static void ril_data_settings_changed(struct ril_sim_settings *settings,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||||
struct ril_radio *radio, struct ril_network *network,
|
struct ril_radio *radio, struct ril_network *network,
|
||||||
GRilIoChannel *io, enum ril_data_allow_data_opt opt)
|
GRilIoChannel *io, enum ril_data_allow_data_opt allow_data,
|
||||||
|
enum ril_data_call_format data_call_format)
|
||||||
{
|
{
|
||||||
GASSERT(dm);
|
GASSERT(dm);
|
||||||
if (G_LIKELY(dm)) {
|
if (G_LIKELY(dm)) {
|
||||||
@@ -1034,10 +1039,10 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
|||||||
struct ril_sim_settings *settings = network->settings;
|
struct ril_sim_settings *settings = network->settings;
|
||||||
GRilIoRequest *req = grilio_request_new();
|
GRilIoRequest *req = grilio_request_new();
|
||||||
|
|
||||||
switch (opt) {
|
switch (allow_data) {
|
||||||
case RIL_ALLOW_DATA_ON:
|
case RIL_ALLOW_DATA_ON:
|
||||||
case RIL_ALLOW_DATA_OFF:
|
case RIL_ALLOW_DATA_OFF:
|
||||||
priv->allow_data = opt;
|
priv->allow_data = allow_data;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
@@ -1049,6 +1054,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->data_call_format = data_call_format;
|
||||||
priv->log_prefix = (name && name[0]) ?
|
priv->log_prefix = (name && name[0]) ?
|
||||||
g_strconcat(name, " ", NULL) : g_strdup("");
|
g_strconcat(name, " ", NULL) : g_strdup("");
|
||||||
|
|
||||||
@@ -1077,6 +1083,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
|||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
|
|
||||||
dm->data_list = g_slist_append(dm->data_list, self);
|
dm->data_list = g_slist_append(dm->data_list, self);
|
||||||
|
ril_data_manager_check_network_mode(dm);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1379,6 +1386,16 @@ void ril_data_manager_unref(struct ril_data_manager *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The 3G/LTE handover thing only makes sense if we are managing
|
||||||
|
* more than one SIM slot. Otherwise leave things where they are.
|
||||||
|
*/
|
||||||
|
return (self->data_list && self->data_list->next &&
|
||||||
|
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean ril_data_manager_requests_pending(struct ril_data_manager *self)
|
static gboolean ril_data_manager_requests_pending(struct ril_data_manager *self)
|
||||||
{
|
{
|
||||||
GSList *l;
|
GSList *l;
|
||||||
@@ -1462,16 +1479,6 @@ static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The 3G/LTE handover thing only makes sense if we are managing
|
|
||||||
* more than one SIM slot. Otherwise leave things where they are.
|
|
||||||
*/
|
|
||||||
return (self->data_list && self->data_list->next &&
|
|
||||||
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
||||||
struct ril_data *data)
|
struct ril_data *data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ enum ril_data_allow_data_opt {
|
|||||||
RIL_ALLOW_DATA_OFF
|
RIL_ALLOW_DATA_OFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ril_data_call_format {
|
||||||
|
RIL_DATA_CALL_FORMAT_AUTO,
|
||||||
|
RIL_DATA_CALL_FORMAT_6 = 6,
|
||||||
|
RIL_DATA_CALL_FORMAT_9 = 9,
|
||||||
|
RIL_DATA_CALL_FORMAT_11 = 11
|
||||||
|
};
|
||||||
|
|
||||||
enum ril_data_role {
|
enum ril_data_role {
|
||||||
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
||||||
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
||||||
@@ -79,8 +86,9 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
|||||||
int ril_status, void *arg);
|
int ril_status, void *arg);
|
||||||
|
|
||||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||||
struct ril_radio *radio, struct ril_network *network,
|
struct ril_radio *radio, struct ril_network *network,
|
||||||
GRilIoChannel *io, enum ril_data_allow_data_opt opt);
|
GRilIoChannel *io, enum ril_data_allow_data_opt allow_data,
|
||||||
|
enum ril_data_call_format data_call_format);
|
||||||
struct ril_data *ril_data_ref(struct ril_data *data);
|
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||||
void ril_data_unref(struct ril_data *data);
|
void ril_data_unref(struct ril_data *data);
|
||||||
gboolean ril_data_allowed(struct ril_data *data);
|
gboolean ril_data_allowed(struct ril_data *data);
|
||||||
|
|||||||
@@ -436,9 +436,30 @@ static int ril_network_pref_mode_expected(struct ril_network *self)
|
|||||||
{
|
{
|
||||||
struct ril_sim_settings *settings = self->settings;
|
struct ril_sim_settings *settings = self->settings;
|
||||||
struct ril_network_priv *priv = self->priv;
|
struct ril_network_priv *priv = self->priv;
|
||||||
const enum ofono_radio_access_mode pref_mode = priv->max_pref_mode ?
|
|
||||||
MIN(settings->pref_mode, priv->max_pref_mode) :
|
/*
|
||||||
settings->pref_mode;
|
* On dual-SIM phones such as Jolla C only one slot at a time
|
||||||
|
* is allowed to use LTE. Even if the slot which has been using
|
||||||
|
* LTE gets powered off, we still need to explicitely set its
|
||||||
|
* preferred mode to GSM, to make LTE machinery available to
|
||||||
|
* the other slot. This sort of behaviour might not be necessary
|
||||||
|
* on some hardware and can (should) be made configurable when
|
||||||
|
* it becomes necessary.
|
||||||
|
*/
|
||||||
|
const enum ofono_radio_access_mode max_pref_mode =
|
||||||
|
(priv->radio->state == RADIO_STATE_ON) ? priv->max_pref_mode :
|
||||||
|
OFONO_RADIO_ACCESS_MODE_GSM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OFONO_RADIO_ACCESS_MODE_ANY is zero. If both pref_mode
|
||||||
|
* and max_pref_mode are not ANY, we pick the smallest value.
|
||||||
|
* Otherwise we take any non-zero value if there is one.
|
||||||
|
*/
|
||||||
|
const enum ofono_radio_access_mode pref_mode =
|
||||||
|
(settings->pref_mode && max_pref_mode) ?
|
||||||
|
MIN(settings->pref_mode, max_pref_mode) :
|
||||||
|
settings->pref_mode ? settings->pref_mode :
|
||||||
|
max_pref_mode;
|
||||||
return ril_network_mode_to_rat(self, pref_mode);
|
return ril_network_mode_to_rat(self, pref_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +576,31 @@ static int ril_network_parse_pref_resp(const void *data, guint len)
|
|||||||
return pref;
|
return pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_network_startup_query_pref_mode_cb(GRilIoChannel *io,
|
||||||
|
int status, const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
if (status == RIL_E_SUCCESS) {
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
const enum ofono_radio_access_mode pref_mode = self->pref_mode;
|
||||||
|
|
||||||
|
priv->rat = ril_network_parse_pref_resp(data, len);
|
||||||
|
self->pref_mode = ril_network_rat_to_mode(priv->rat);
|
||||||
|
DBG_(self, "rat mode %d (%s)", priv->rat,
|
||||||
|
ofono_radio_access_mode_to_string(self->pref_mode));
|
||||||
|
|
||||||
|
if (self->pref_mode != pref_mode) {
|
||||||
|
ril_network_emit(self, SIGNAL_PREF_MODE_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlike ril_network_query_pref_mode_cb, this one always
|
||||||
|
* checks the preferred mode.
|
||||||
|
*/
|
||||||
|
ril_network_check_pref_mode(self, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_network_query_pref_mode_cb(GRilIoChannel *io, int status,
|
static void ril_network_query_pref_mode_cb(GRilIoChannel *io, int status,
|
||||||
const void *data, guint len, void *user_data)
|
const void *data, guint len, void *user_data)
|
||||||
{
|
{
|
||||||
@@ -661,8 +707,11 @@ static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
|
|||||||
|
|
||||||
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
|
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
|
||||||
{
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(data);
|
||||||
|
|
||||||
|
ril_network_check_pref_mode(self, FALSE);
|
||||||
if (radio->state == RADIO_STATE_ON) {
|
if (radio->state == RADIO_STATE_ON) {
|
||||||
ril_network_poll_state(RIL_NETWORK(data));
|
ril_network_poll_state(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,7 +802,9 @@ struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
|
|||||||
* Query the initial state. Querying network state before the radio
|
* Query the initial state. Querying network state before the radio
|
||||||
* has been turned on makes RIL unhappy.
|
* has been turned on makes RIL unhappy.
|
||||||
*/
|
*/
|
||||||
ril_network_query_pref_mode(self);
|
grilio_queue_send_request_full(priv->q, NULL,
|
||||||
|
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||||
|
ril_network_startup_query_pref_mode_cb, NULL, self);
|
||||||
if (radio->state == RADIO_STATE_ON) {
|
if (radio->state == RADIO_STATE_ON) {
|
||||||
ril_network_poll_state(self);
|
ril_network_poll_state(self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
|
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
|
||||||
#define RILMODEM_DEFAULT_DATA_OPT RIL_ALLOW_DATA_AUTO
|
#define RILMODEM_DEFAULT_DATA_OPT RIL_ALLOW_DATA_AUTO
|
||||||
#define RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
|
#define RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
|
||||||
|
#define RILMODEM_DEFAULT_DATA_CALL_FORMAT RIL_DATA_CALL_FORMAT_AUTO
|
||||||
#define RILMODEM_DEFAULT_EMPTY_PIN_QUERY TRUE /* optimistic */
|
#define RILMODEM_DEFAULT_EMPTY_PIN_QUERY TRUE /* optimistic */
|
||||||
|
|
||||||
#define RILCONF_SETTINGS_EMPTY "EmptyConfig"
|
#define RILCONF_SETTINGS_EMPTY "EmptyConfig"
|
||||||
@@ -71,6 +72,7 @@
|
|||||||
#define RILCONF_ECCLIST_FILE "ecclistFile"
|
#define RILCONF_ECCLIST_FILE "ecclistFile"
|
||||||
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
||||||
#define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery"
|
#define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery"
|
||||||
|
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
|
||||||
|
|
||||||
#define RIL_STORE "ril"
|
#define RIL_STORE "ril"
|
||||||
#define RIL_STORE_GROUP "Settings"
|
#define RIL_STORE_GROUP "Settings"
|
||||||
@@ -123,6 +125,7 @@ struct ril_slot {
|
|||||||
int index;
|
int index;
|
||||||
int sim_flags;
|
int sim_flags;
|
||||||
enum ril_data_allow_data_opt allow_data_opt;
|
enum ril_data_allow_data_opt allow_data_opt;
|
||||||
|
enum ril_data_call_format data_call_format;
|
||||||
struct ril_slot_config config;
|
struct ril_slot_config config;
|
||||||
struct ril_plugin_priv *plugin;
|
struct ril_plugin_priv *plugin;
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
@@ -969,7 +972,8 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
|||||||
|
|
||||||
GASSERT(!slot->data);
|
GASSERT(!slot->data);
|
||||||
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
|
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
|
||||||
slot->radio, slot->network, slot->io, slot->allow_data_opt);
|
slot->radio, slot->network, slot->io, slot->allow_data_opt,
|
||||||
|
slot->data_call_format);
|
||||||
|
|
||||||
GASSERT(!slot->cell_info);
|
GASSERT(!slot->cell_info);
|
||||||
if (slot->io->ril_version > 8) {
|
if (slot->io->ril_version > 8) {
|
||||||
@@ -1064,6 +1068,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
|
|||||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||||
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||||
|
slot->data_call_format = RILMODEM_DEFAULT_DATA_CALL_FORMAT;
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1153,6 +1158,7 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
strval = ril_config_get_string(file, group,
|
strval = ril_config_get_string(file, group,
|
||||||
RILCONF_ALLOW_DATA_REQ);
|
RILCONF_ALLOW_DATA_REQ);
|
||||||
if (strval) {
|
if (strval) {
|
||||||
|
strval = g_strstrip(strval);
|
||||||
slot->allow_data_opt =
|
slot->allow_data_opt =
|
||||||
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
|
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
|
||||||
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
|
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
|
||||||
@@ -1164,6 +1170,27 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
g_free(strval);
|
g_free(strval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strval = ril_config_get_string(file, group,
|
||||||
|
RILCONF_DATA_CALL_FORMAT);
|
||||||
|
if (strval) {
|
||||||
|
strval = g_strstrip(strval);
|
||||||
|
slot->data_call_format =
|
||||||
|
!strcmp(strval, "6") ? RIL_DATA_CALL_FORMAT_6:
|
||||||
|
!strcmp(strval, "9") ? RIL_DATA_CALL_FORMAT_9:
|
||||||
|
!strcmp(strval, "11")? RIL_DATA_CALL_FORMAT_11:
|
||||||
|
RIL_DATA_CALL_FORMAT_AUTO;
|
||||||
|
if (slot->data_call_format ==
|
||||||
|
RIL_DATA_CALL_FORMAT_AUTO) {
|
||||||
|
DBG("%s: %s auto", group,
|
||||||
|
RILCONF_DATA_CALL_FORMAT);
|
||||||
|
} else {
|
||||||
|
DBG("%s: %s %d", group,
|
||||||
|
RILCONF_DATA_CALL_FORMAT,
|
||||||
|
slot->data_call_format);
|
||||||
|
}
|
||||||
|
g_free(strval);
|
||||||
|
}
|
||||||
|
|
||||||
slot->ecclist_file = ril_config_get_string(file, group,
|
slot->ecclist_file = ril_config_get_string(file, group,
|
||||||
RILCONF_ECCLIST_FILE);
|
RILCONF_ECCLIST_FILE);
|
||||||
if (slot->ecclist_file && slot->ecclist_file[0]) {
|
if (slot->ecclist_file && slot->ecclist_file[0]) {
|
||||||
|
|||||||
@@ -113,3 +113,15 @@ socket=/dev/socket/rild
|
|||||||
# Default is true
|
# Default is true
|
||||||
#
|
#
|
||||||
#emptyPinQuery=true
|
#emptyPinQuery=true
|
||||||
|
|
||||||
|
# Different RILs use different data call structures which don't necessarily
|
||||||
|
# match the format specified in the data list header. The header may have
|
||||||
|
# version 9 but the list may contain RIL_Data_Call_Response_v6 structures,
|
||||||
|
# list version 10 may contain RIL_Data_Call_Response_v11 and so on. By default
|
||||||
|
# ofono assumes that the version from the list header matches the contents
|
||||||
|
# but sometimes you have to explicitly tell ofono which one to use.
|
||||||
|
# Possible values are 6, 9, 11 and auto.
|
||||||
|
#
|
||||||
|
# Default is auto
|
||||||
|
#
|
||||||
|
#dataCallFormat=auto
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* oFono - Open Source Telephony
|
* oFono - Open Source Telephony
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2015 Jolla Ltd.
|
* Copyright (C) 2012-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -12,11 +11,6 @@
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@@ -35,9 +29,34 @@
|
|||||||
|
|
||||||
#include "ofono.h"
|
#include "ofono.h"
|
||||||
|
|
||||||
|
#define NTD_WAIT_TIMEOUT (500) /* ms */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are 3 distinct states here:
|
||||||
|
*
|
||||||
|
* 1. !valid
|
||||||
|
*
|
||||||
|
* Initial state, no time/timezone information whatsoever.
|
||||||
|
*
|
||||||
|
* 2. valid && !mccmnc
|
||||||
|
*
|
||||||
|
* Time/timezone information has been received from the network,
|
||||||
|
* but no MCC and MNC yet.
|
||||||
|
*
|
||||||
|
* 3. valid && mccmnc
|
||||||
|
*
|
||||||
|
* Time/timezone information is fully available.
|
||||||
|
*
|
||||||
|
*/
|
||||||
struct nt_data {
|
struct nt_data {
|
||||||
|
struct ofono_modem *modem;
|
||||||
|
struct ofono_netreg *netreg;
|
||||||
|
unsigned int netreg_watch_id;
|
||||||
|
unsigned int netreg_status_watch_id;
|
||||||
|
guint mccmnc_wait_id;
|
||||||
|
|
||||||
gboolean time_available;
|
gboolean time_available;
|
||||||
gboolean time_pending;
|
gboolean valid;
|
||||||
|
|
||||||
time_t nw_time_utc;
|
time_t nw_time_utc;
|
||||||
time_t received;
|
time_t received;
|
||||||
@@ -47,27 +66,11 @@ struct nt_data {
|
|||||||
|
|
||||||
char *mcc;
|
char *mcc;
|
||||||
char *mnc;
|
char *mnc;
|
||||||
char* path;
|
|
||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nt_data *nettime_new(const char *path)
|
#define DBG_(ntd,fmt,args...) \
|
||||||
{
|
DBG("%s " fmt, ofono_modem_get_path((ntd)->modem), ##args)
|
||||||
struct nt_data *ntd = g_new0(struct nt_data, 1);
|
|
||||||
|
|
||||||
ntd->path = g_strdup(path);
|
|
||||||
ntd->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
|
||||||
return ntd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nettime_free(struct nt_data *ntd)
|
|
||||||
{
|
|
||||||
dbus_connection_unref(ntd->conn);
|
|
||||||
g_free(ntd->path);
|
|
||||||
g_free(ntd->mcc);
|
|
||||||
g_free(ntd->mnc);
|
|
||||||
g_free(ntd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean nettime_encode_time_format(struct tm *tm,
|
static gboolean nettime_encode_time_format(struct tm *tm,
|
||||||
const struct ofono_network_time *time)
|
const struct ofono_network_time *time)
|
||||||
@@ -110,7 +113,7 @@ static int nettime_fill_time_notification(DBusMessage *msg, struct nt_data *ntd)
|
|||||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
||||||
"{sv}",
|
"{sv}",
|
||||||
&iter_array);
|
&iter_array);
|
||||||
if (ntd->time_pending) {
|
if (ntd->valid && ntd->mcc && ntd->mnc) {
|
||||||
if (ntd->time_available) {
|
if (ntd->time_available) {
|
||||||
utc_long = (dbus_int64_t) ntd->nw_time_utc;
|
utc_long = (dbus_int64_t) ntd->nw_time_utc;
|
||||||
ofono_dbus_dict_append(&iter_array,
|
ofono_dbus_dict_append(&iter_array,
|
||||||
@@ -145,7 +148,7 @@ static int nettime_fill_time_notification(DBusMessage *msg, struct nt_data *ntd)
|
|||||||
DBUS_TYPE_STRING,
|
DBUS_TYPE_STRING,
|
||||||
&ntd->mnc);
|
&ntd->mnc);
|
||||||
} else {
|
} else {
|
||||||
DBG("fill_time_notification: time not available");
|
DBG_(ntd, "time not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_message_iter_close_container(&iter, &iter_array);
|
dbus_message_iter_close_container(&iter, &iter_array);
|
||||||
@@ -177,23 +180,209 @@ static const GDBusSignalTable nettime_signals[] = {
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void nettime_send_signal(struct nt_data *ntd)
|
||||||
|
{
|
||||||
|
DBusMessage *signal =
|
||||||
|
dbus_message_new_signal(ofono_modem_get_path(ntd->modem),
|
||||||
|
OFONO_NETWORK_TIME_INTERFACE, "NetworkTimeChanged");
|
||||||
|
|
||||||
|
DBG_(ntd, "");
|
||||||
|
nettime_fill_time_notification(signal, ntd);
|
||||||
|
g_dbus_send_message(ntd->conn, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_set_mcc_mnc(struct nt_data *ntd, const char *mcc,
|
||||||
|
const char *mnc)
|
||||||
|
{
|
||||||
|
if (g_strcmp0(ntd->mcc, mcc)) {
|
||||||
|
g_free(ntd->mcc);
|
||||||
|
ntd->mcc = g_strdup(mcc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(ntd->mnc, mnc)) {
|
||||||
|
g_free(ntd->mnc);
|
||||||
|
ntd->mnc = g_strdup(mnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntd->mcc && ntd->mnc) {
|
||||||
|
DBG_(ntd, "MCC: %s, MNC: %s", ntd->mcc, ntd->mnc);
|
||||||
|
|
||||||
|
if (ntd->mccmnc_wait_id) {
|
||||||
|
/* We have been waiting for MCC and MNC */
|
||||||
|
g_source_remove(ntd->mccmnc_wait_id);
|
||||||
|
ntd->mccmnc_wait_id = 0;
|
||||||
|
nettime_send_signal(ntd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_netreg_status_watch_cb(int status, int lac, int ci,
|
||||||
|
int tech, const char *mcc, const char *mnc,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
nettime_set_mcc_mnc(userdata, mcc, mnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_netreg_status_watch_done(void *userdata)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = userdata;
|
||||||
|
|
||||||
|
DBG_(ntd, "");
|
||||||
|
ntd->netreg_status_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_set_netreg(struct nt_data *ntd,
|
||||||
|
struct ofono_netreg *netreg)
|
||||||
|
{
|
||||||
|
if (ntd->netreg != netreg) {
|
||||||
|
ntd->valid = FALSE;
|
||||||
|
ntd->netreg = netreg;
|
||||||
|
if (netreg) {
|
||||||
|
nettime_set_mcc_mnc(ntd,
|
||||||
|
ofono_netreg_get_mcc(netreg),
|
||||||
|
ofono_netreg_get_mnc(netreg));
|
||||||
|
ntd->netreg_status_watch_id =
|
||||||
|
__ofono_netreg_add_status_watch(netreg,
|
||||||
|
nettime_netreg_status_watch_cb, ntd,
|
||||||
|
nettime_netreg_status_watch_done);
|
||||||
|
} else {
|
||||||
|
g_free(ntd->mcc);
|
||||||
|
g_free(ntd->mnc);
|
||||||
|
ntd->mcc = NULL;
|
||||||
|
ntd->mnc = NULL;
|
||||||
|
ntd->netreg_status_watch_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_netreg_watch_cb(struct ofono_atom *atom,
|
||||||
|
enum ofono_atom_watch_condition cond, void *userdata)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = userdata;
|
||||||
|
|
||||||
|
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
|
||||||
|
DBG_(ntd, "registered");
|
||||||
|
nettime_set_netreg(ntd, __ofono_atom_get_data(atom));
|
||||||
|
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
|
||||||
|
DBG_(ntd, "unregistered");
|
||||||
|
nettime_set_netreg(ntd, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_netreg_watch_done(void *userdata)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = userdata;
|
||||||
|
|
||||||
|
DBG_(ntd, "");
|
||||||
|
ntd->netreg_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean nettime_timeout_cb(gpointer data)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = data;
|
||||||
|
|
||||||
|
DBG_(ntd, "timed out");
|
||||||
|
ntd->mccmnc_wait_id = 0;
|
||||||
|
ntd->valid = FALSE;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nt_data *nettime_new(struct ofono_modem *modem)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = g_new0(struct nt_data, 1);
|
||||||
|
struct ofono_atom *netreg_atom = __ofono_modem_find_atom(modem,
|
||||||
|
OFONO_ATOM_TYPE_NETREG);
|
||||||
|
|
||||||
|
ntd->modem = modem;
|
||||||
|
ntd->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||||
|
ntd->netreg_watch_id = __ofono_modem_add_atom_watch(modem,
|
||||||
|
OFONO_ATOM_TYPE_NETREG, nettime_netreg_watch_cb,
|
||||||
|
ntd, nettime_netreg_watch_done);
|
||||||
|
|
||||||
|
if (netreg_atom) {
|
||||||
|
nettime_set_netreg(ntd, __ofono_atom_get_data(netreg_atom));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ntd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_free(struct nt_data *ntd)
|
||||||
|
{
|
||||||
|
if (ntd->mccmnc_wait_id)
|
||||||
|
g_source_remove(ntd->mccmnc_wait_id);
|
||||||
|
|
||||||
|
if (ntd->netreg_status_watch_id)
|
||||||
|
__ofono_netreg_remove_status_watch(ntd->netreg,
|
||||||
|
ntd->netreg_status_watch_id);
|
||||||
|
|
||||||
|
if (ntd->netreg_watch_id)
|
||||||
|
__ofono_modem_remove_atom_watch(ntd->modem,
|
||||||
|
ntd->netreg_watch_id);
|
||||||
|
|
||||||
|
dbus_connection_unref(ntd->conn);
|
||||||
|
g_free(ntd->mcc);
|
||||||
|
g_free(ntd->mnc);
|
||||||
|
g_free(ntd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nettime_info_received(struct ofono_nettime_context *context,
|
||||||
|
struct ofono_network_time *info)
|
||||||
|
{
|
||||||
|
struct nt_data *ntd = context->data;
|
||||||
|
struct tm t;
|
||||||
|
|
||||||
|
if (!ntd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ntd->received = nettime_get_monotonic_time();
|
||||||
|
ntd->valid = TRUE;
|
||||||
|
ntd->dst = info->dst;
|
||||||
|
ntd->time_zone = info->utcoff;
|
||||||
|
ntd->time_available = nettime_encode_time_format(&t, info);
|
||||||
|
if (ntd->time_available) {
|
||||||
|
ntd->nw_time_utc = timegm(&t);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_(ntd, "time: %04d-%02d-%02d %02d:%02d:%02d%c%02d:%02d (DST=%d)",
|
||||||
|
info->year, info->mon, info->mday, info->hour,
|
||||||
|
info->min, info->sec, info->utcoff > 0 ? '+' : '-',
|
||||||
|
abs(info->utcoff) / 3600, (abs(info->utcoff) % 3600) / 60,
|
||||||
|
info->dst);
|
||||||
|
DBG_(ntd, "UTC timestamp: %li, Received (monotonic time): %li",
|
||||||
|
ntd->nw_time_utc, ntd->received);
|
||||||
|
|
||||||
|
if (ntd->mcc && ntd->mnc) {
|
||||||
|
DBG_(ntd, "MCC: %s, MNC: %s", ntd->mcc, ntd->mnc);
|
||||||
|
nettime_send_signal(ntd);
|
||||||
|
} else {
|
||||||
|
DBG_(ntd, "no MCC/MNC yet");
|
||||||
|
|
||||||
|
if (ntd->mccmnc_wait_id)
|
||||||
|
g_source_remove(ntd->mccmnc_wait_id);
|
||||||
|
|
||||||
|
ntd->mccmnc_wait_id = g_timeout_add(NTD_WAIT_TIMEOUT,
|
||||||
|
nettime_timeout_cb, ntd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int nettime_probe(struct ofono_nettime_context *context)
|
static int nettime_probe(struct ofono_nettime_context *context)
|
||||||
{
|
{
|
||||||
struct nt_data *ntd = nettime_new(ofono_modem_get_path(context->modem));
|
struct nt_data *ntd = nettime_new(context->modem);
|
||||||
|
const char *path = ofono_modem_get_path(context->modem);
|
||||||
|
|
||||||
DBG("Network time probe for modem: %p (%s)", context->modem, ntd->path);
|
DBG("Network time probe for modem: %p (%s)", context->modem, path);
|
||||||
if (g_dbus_register_interface(ntd->conn, ntd->path,
|
if (g_dbus_register_interface(ntd->conn, path,
|
||||||
OFONO_NETWORK_TIME_INTERFACE, nettime_methods,
|
OFONO_NETWORK_TIME_INTERFACE, nettime_methods,
|
||||||
nettime_signals, NULL, ntd, NULL)) {
|
nettime_signals, NULL, ntd, NULL)) {
|
||||||
context->data = ntd;
|
context->data = ntd;
|
||||||
ofono_info("Registered interface %s, path %s",
|
ofono_info("Registered interface %s, path %s",
|
||||||
OFONO_NETWORK_TIME_INTERFACE, ntd->path);
|
OFONO_NETWORK_TIME_INTERFACE, path);
|
||||||
ofono_modem_add_interface(context->modem,
|
ofono_modem_add_interface(context->modem,
|
||||||
OFONO_NETWORK_TIME_INTERFACE);
|
OFONO_NETWORK_TIME_INTERFACE);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
ofono_error("Could not register interface %s, path %s",
|
ofono_error("Could not register interface %s, path %s",
|
||||||
OFONO_NETWORK_TIME_INTERFACE, ntd->path);
|
OFONO_NETWORK_TIME_INTERFACE, path);
|
||||||
nettime_free(ntd);
|
nettime_free(ntd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -202,77 +391,16 @@ static int nettime_probe(struct ofono_nettime_context *context)
|
|||||||
static void nettime_remove(struct ofono_nettime_context *context)
|
static void nettime_remove(struct ofono_nettime_context *context)
|
||||||
{
|
{
|
||||||
struct nt_data *ntd = context->data;
|
struct nt_data *ntd = context->data;
|
||||||
|
const char *path = ofono_modem_get_path(context->modem);
|
||||||
|
|
||||||
DBG("Network time remove for modem: %p (%s)", context->modem,
|
DBG("Network time remove for modem: %p (%s)", context->modem, path);
|
||||||
ofono_modem_get_path(context->modem));
|
|
||||||
ofono_modem_remove_interface(context->modem,
|
ofono_modem_remove_interface(context->modem,
|
||||||
OFONO_NETWORK_TIME_INTERFACE);
|
OFONO_NETWORK_TIME_INTERFACE);
|
||||||
if (!g_dbus_unregister_interface(ntd->conn, ntd->path,
|
g_dbus_unregister_interface(ntd->conn, path,
|
||||||
OFONO_NETWORK_TIME_INTERFACE)) {
|
OFONO_NETWORK_TIME_INTERFACE);
|
||||||
ofono_error("Network time: could not unregister interface %s"
|
|
||||||
" for %s", OFONO_NETWORK_TIME_INTERFACE, ntd->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
nettime_free(ntd);
|
nettime_free(ntd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nettime_send_signal(struct nt_data *ntd)
|
|
||||||
{
|
|
||||||
DBusMessage *signal = dbus_message_new_signal(ntd->path,
|
|
||||||
OFONO_NETWORK_TIME_INTERFACE,
|
|
||||||
"NetworkTimeChanged");
|
|
||||||
|
|
||||||
nettime_fill_time_notification(signal, ntd);
|
|
||||||
g_dbus_send_message(ntd->conn, signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nettime_info_received(struct ofono_nettime_context *context,
|
|
||||||
struct ofono_network_time *info)
|
|
||||||
{
|
|
||||||
struct nt_data *ntd = context->data;
|
|
||||||
struct ofono_netreg *netreg;
|
|
||||||
const char *mcc;
|
|
||||||
const char *mnc;
|
|
||||||
struct tm t;
|
|
||||||
|
|
||||||
if (!ntd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
netreg = __ofono_atom_get_data(__ofono_modem_find_atom(
|
|
||||||
context->modem, OFONO_ATOM_TYPE_NETREG));
|
|
||||||
mcc = ofono_netreg_get_mcc(netreg);
|
|
||||||
mnc = ofono_netreg_get_mnc(netreg);
|
|
||||||
|
|
||||||
if (!mcc || !mnc) {
|
|
||||||
DBG("Incomplete network time received, ignoring");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(ntd->mcc);
|
|
||||||
g_free(ntd->mnc);
|
|
||||||
ntd->mcc = g_strdup(mcc);
|
|
||||||
ntd->mnc = g_strdup(mnc);
|
|
||||||
ntd->received = nettime_get_monotonic_time();
|
|
||||||
ntd->time_pending = TRUE;
|
|
||||||
ntd->dst = info->dst;
|
|
||||||
ntd->time_zone = info->utcoff;
|
|
||||||
ntd->time_available = nettime_encode_time_format(&t, info);
|
|
||||||
if (ntd->time_available) {
|
|
||||||
ntd->nw_time_utc = timegm(&t);
|
|
||||||
}
|
|
||||||
|
|
||||||
nettime_send_signal(ntd);
|
|
||||||
DBG("modem: %p (%s)", context->modem, ntd->path);
|
|
||||||
DBG("time: %04d-%02d-%02d %02d:%02d:%02d%c%02d:%02d (DST=%d)",
|
|
||||||
info->year, info->mon, info->mday, info->hour,
|
|
||||||
info->min, info->sec, info->utcoff > 0 ? '+' : '-',
|
|
||||||
abs(info->utcoff) / 3600, (abs(info->utcoff) % 3600) / 60,
|
|
||||||
info->dst);
|
|
||||||
DBG("UTC timestamp: %li, Received (monotonic time): %li",
|
|
||||||
ntd->nw_time_utc, ntd->received);
|
|
||||||
DBG("MCC: %s, MNC: %s", ntd->mcc, ntd->mnc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ofono_nettime_driver driver = {
|
static struct ofono_nettime_driver driver = {
|
||||||
.name = "Network Time",
|
.name = "Network Time",
|
||||||
.probe = nettime_probe,
|
.probe = nettime_probe,
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ struct pri_context {
|
|||||||
struct ofono_gprs *gprs;
|
struct ofono_gprs *gprs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void gprs_attached_update(struct ofono_gprs *gprs);
|
||||||
static void gprs_netreg_update(struct ofono_gprs *gprs);
|
static void gprs_netreg_update(struct ofono_gprs *gprs);
|
||||||
static void gprs_deactivate_next(struct ofono_gprs *gprs);
|
static void gprs_deactivate_next(struct ofono_gprs *gprs);
|
||||||
static void write_context_settings(struct ofono_gprs *gprs,
|
static void write_context_settings(struct ofono_gprs *gprs,
|
||||||
@@ -1148,6 +1149,16 @@ static void pri_deactivate_callback(const struct ofono_error *error, void *data)
|
|||||||
ofono_dbus_signal_property_changed(conn, ctx->path,
|
ofono_dbus_signal_property_changed(conn, ctx->path,
|
||||||
OFONO_CONNECTION_CONTEXT_INTERFACE,
|
OFONO_CONNECTION_CONTEXT_INTERFACE,
|
||||||
"Active", DBUS_TYPE_BOOLEAN, &value);
|
"Active", DBUS_TYPE_BOOLEAN, &value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If "Attached" property was about to be signalled as TRUE but there
|
||||||
|
* were still active contexts, try again to signal "Attached" property
|
||||||
|
* to registered applications after active contexts have been released.
|
||||||
|
*/
|
||||||
|
if (ctx->gprs->flags & GPRS_FLAG_ATTACHED_UPDATE) {
|
||||||
|
ctx->gprs->flags &= ~GPRS_FLAG_ATTACHED_UPDATE;
|
||||||
|
gprs_attached_update(ctx->gprs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pri_read_settings_callback(const struct ofono_error *error,
|
static void pri_read_settings_callback(const struct ofono_error *error,
|
||||||
@@ -2358,13 +2369,13 @@ static DBusMessage *gprs_remove_context(DBusConnection *conn,
|
|||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
return __ofono_error_not_found(msg);
|
return __ofono_error_not_found(msg);
|
||||||
|
|
||||||
|
/* This context is already being messed with */
|
||||||
|
if (ctx->pending)
|
||||||
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (ctx->active) {
|
if (ctx->active) {
|
||||||
struct ofono_gprs_context *gc = ctx->context_driver;
|
struct ofono_gprs_context *gc = ctx->context_driver;
|
||||||
|
|
||||||
/* This context is already being messed with */
|
|
||||||
if (ctx->pending)
|
|
||||||
return __ofono_error_busy(msg);
|
|
||||||
|
|
||||||
gprs->pending = dbus_message_ref(msg);
|
gprs->pending = dbus_message_ref(msg);
|
||||||
gc->driver->deactivate_primary(gc, ctx->context.cid,
|
gc->driver->deactivate_primary(gc, ctx->context.cid,
|
||||||
gprs_deactivate_for_remove, ctx);
|
gprs_deactivate_for_remove, ctx);
|
||||||
|
|||||||
Reference in New Issue
Block a user