mirror of git://git.sysmocom.de/ofono
stk: Handle the Timer Management proactive command
This commit is contained in:
parent
c0db55513d
commit
bd33ab6a6f
165
src/stk.c
165
src/stk.c
|
@ -31,6 +31,7 @@
|
|||
#include <glib.h>
|
||||
#include <gdbus.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
|
@ -40,6 +41,11 @@
|
|||
|
||||
static GSList *g_drivers = NULL;
|
||||
|
||||
struct stk_timer {
|
||||
time_t expiry;
|
||||
time_t start;
|
||||
};
|
||||
|
||||
struct ofono_stk {
|
||||
const struct ofono_stk_driver *driver;
|
||||
void *driver_data;
|
||||
|
@ -49,6 +55,9 @@ struct ofono_stk {
|
|||
gboolean cancelled;
|
||||
GQueue *envelope_q;
|
||||
|
||||
struct stk_timer timers[8];
|
||||
guint timers_source;
|
||||
|
||||
struct sms_submit_req *sms_submit_req;
|
||||
char *idle_mode_text;
|
||||
};
|
||||
|
@ -69,6 +78,7 @@ struct sms_submit_req {
|
|||
#define ENVELOPE_RETRIES_DEFAULT 5
|
||||
|
||||
static void envelope_queue_run(struct ofono_stk *stk);
|
||||
static void timers_update(struct ofono_stk *stk);
|
||||
|
||||
static int stk_respond(struct ofono_stk *stk, struct stk_response *rsp,
|
||||
ofono_stk_generic_cb_t cb)
|
||||
|
@ -378,6 +388,152 @@ out:
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void timer_expiration_cb(struct ofono_stk *stk, gboolean ok,
|
||||
const unsigned char *data, int len)
|
||||
{
|
||||
if (!ok) {
|
||||
ofono_error("Timer Expiration reporting failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len)
|
||||
ofono_error("Timer Expiration returned %i bytes of data",
|
||||
len);
|
||||
|
||||
DBG("Timer Expiration reporting to UICC reported no error");
|
||||
}
|
||||
|
||||
static gboolean timers_cb(gpointer user_data)
|
||||
{
|
||||
struct ofono_stk *stk = user_data;
|
||||
|
||||
stk->timers_source = 0;
|
||||
|
||||
timers_update(stk);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void timer_value_from_seconds(struct stk_timer_value *val, int seconds)
|
||||
{
|
||||
val->has_value = TRUE;
|
||||
val->hour = seconds / 3600;
|
||||
seconds -= val->hour * 3600;
|
||||
val->minute = seconds / 60;
|
||||
seconds -= val->minute * 60;
|
||||
val->second = seconds;
|
||||
}
|
||||
|
||||
static void timers_update(struct ofono_stk *stk)
|
||||
{
|
||||
time_t min = 0, now = time(NULL);
|
||||
int i;
|
||||
|
||||
if (stk->timers_source) {
|
||||
g_source_remove(stk->timers_source);
|
||||
stk->timers_source = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (!stk->timers[i].expiry)
|
||||
continue;
|
||||
|
||||
if (stk->timers[i].expiry <= now) {
|
||||
struct stk_envelope e;
|
||||
int seconds = now - stk->timers[i].start;
|
||||
|
||||
stk->timers[i].expiry = 0;
|
||||
|
||||
memset(&e, 0, sizeof(e));
|
||||
|
||||
e.type = STK_ENVELOPE_TYPE_TIMER_EXPIRATION;
|
||||
e.src = STK_DEVICE_IDENTITY_TYPE_TERMINAL,
|
||||
e.timer_expiration.id = i + 1;
|
||||
timer_value_from_seconds(&e.timer_expiration.value,
|
||||
seconds);
|
||||
|
||||
/*
|
||||
* TODO: resubmit until success, providing current
|
||||
* time difference every time we re-send.
|
||||
*/
|
||||
if (stk_send_envelope(stk, &e, timer_expiration_cb, 0))
|
||||
timer_expiration_cb(stk, FALSE, NULL, -1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stk->timers[i].expiry < now + min || min == 0)
|
||||
min = stk->timers[i].expiry - now;
|
||||
}
|
||||
|
||||
if (min)
|
||||
stk->timers_source = g_timeout_add_seconds(min, timers_cb, stk);
|
||||
}
|
||||
|
||||
static gboolean handle_command_timer_mgmt(const struct stk_command *cmd,
|
||||
struct stk_response *rsp,
|
||||
struct ofono_stk *stk)
|
||||
{
|
||||
int op = cmd->qualifier & 3;
|
||||
time_t seconds, now = time(NULL);
|
||||
struct stk_timer *tmr;
|
||||
|
||||
if (cmd->timer_mgmt.timer_id < 1 || cmd->timer_mgmt.timer_id > 8) {
|
||||
rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tmr = &stk->timers[cmd->timer_mgmt.timer_id - 1];
|
||||
|
||||
switch (op) {
|
||||
case 0: /* Start */
|
||||
seconds = cmd->timer_mgmt.timer_value.second +
|
||||
cmd->timer_mgmt.timer_value.minute * 60 +
|
||||
cmd->timer_mgmt.timer_value.hour * 3600;
|
||||
|
||||
tmr->expiry = now + seconds;
|
||||
tmr->start = now;
|
||||
|
||||
timers_update(stk);
|
||||
break;
|
||||
|
||||
case 1: /* Deactivate */
|
||||
if (!tmr->expiry) {
|
||||
rsp->result.type = STK_RESULT_TYPE_TIMER_CONFLICT;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
seconds = MAX(0, tmr->expiry - now);
|
||||
tmr->expiry = 0;
|
||||
|
||||
timers_update(stk);
|
||||
|
||||
timer_value_from_seconds(&rsp->timer_mgmt.value, seconds);
|
||||
break;
|
||||
|
||||
case 2: /* Get current value */
|
||||
if (!tmr->expiry) {
|
||||
rsp->result.type = STK_RESULT_TYPE_TIMER_CONFLICT;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
seconds = MAX(0, tmr->expiry - now);
|
||||
timer_value_from_seconds(&rsp->timer_mgmt.value, seconds);
|
||||
break;
|
||||
|
||||
default:
|
||||
rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rsp->timer_mgmt.id = cmd->timer_mgmt.timer_id;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void stk_proactive_command_cancel(struct ofono_stk *stk)
|
||||
{
|
||||
if (!stk->pending_cmd)
|
||||
|
@ -460,6 +616,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
|
|||
respond = handle_command_set_idle_text(stk->pending_cmd,
|
||||
&rsp, stk);
|
||||
break;
|
||||
case STK_COMMAND_TYPE_TIMER_MANAGEMENT:
|
||||
respond = handle_command_timer_mgmt(stk->pending_cmd,
|
||||
&rsp, stk);
|
||||
break;
|
||||
}
|
||||
|
||||
if (respond)
|
||||
|
@ -524,6 +684,11 @@ static void stk_unregister(struct ofono_atom *atom)
|
|||
stk->idle_mode_text = NULL;
|
||||
}
|
||||
|
||||
if (stk->timers_source) {
|
||||
g_source_remove(stk->timers_source);
|
||||
stk->timers_source = 0;
|
||||
}
|
||||
|
||||
g_queue_foreach(stk->envelope_q, (GFunc) g_free, NULL);
|
||||
g_queue_free(stk->envelope_q);
|
||||
|
||||
|
|
Loading…
Reference in New Issue