stk: Handle the Get Inkey proactive command

This commit is contained in:
Andrzej Zaborowski 2010-08-04 06:55:02 +02:00 committed by Denis Kenzior
parent 939fc1273c
commit ed169aa02f
1 changed files with 200 additions and 0 deletions

200
src/stk.c
View File

@ -32,6 +32,7 @@
#include <gdbus.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include "ofono.h"
@ -69,6 +70,7 @@ struct ofono_stk {
guint remove_agent_source;
struct sms_submit_req *sms_submit_req;
char *idle_mode_text;
struct timeval get_inkey_start_ts;
};
struct envelope_op {
@ -1134,6 +1136,199 @@ static gboolean handle_command_display_text(const struct stk_command *cmd,
return stk->immediate_response;
}
static void set_get_inkey_duration(struct stk_duration *duration,
struct timeval *start_ts)
{
struct timeval end_ts;
int interval;
gettimeofday(&end_ts, NULL);
interval = (end_ts.tv_usec + 1099999 - start_ts->tv_usec) / 100000;
interval += (end_ts.tv_sec - start_ts->tv_sec) * 10;
interval -= 10;
switch (duration->unit) {
case STK_DURATION_TYPE_MINUTES:
interval = (interval + 59) / 60;
case STK_DURATION_TYPE_SECONDS:
interval = (interval + 9) / 10;
case STK_DURATION_TYPE_SECOND_TENTHS:
break;
}
duration->interval = interval;
}
static void request_confirmation_cb(enum stk_agent_result result,
gboolean confirm,
void *user_data)
{
struct ofono_stk *stk = user_data;
static struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE };
struct stk_command_get_inkey *cmd = &stk->pending_cmd->get_inkey;
uint8_t qualifier = stk->pending_cmd->qualifier;
struct stk_response rsp;
switch (result) {
case STK_AGENT_RESULT_OK:
memset(&rsp, 0, sizeof(rsp));
rsp.result.type = STK_RESULT_TYPE_SUCCESS;
rsp.get_inkey.text.text = confirm ? "" : NULL;
rsp.get_inkey.text.yesno = TRUE;
if (cmd->duration.interval) {
rsp.get_inkey.duration.unit = cmd->duration.unit;
set_get_inkey_duration(&rsp.get_inkey.duration,
&stk->get_inkey_start_ts);
}
if (stk_respond(stk, &rsp, stk_command_cb))
stk_command_cb(&error, stk);
break;
case STK_AGENT_RESULT_BACK:
send_simple_response(stk, STK_RESULT_TYPE_GO_BACK);
break;
case STK_AGENT_RESULT_TIMEOUT:
send_simple_response(stk, STK_RESULT_TYPE_NO_RESPONSE);
break;
case STK_AGENT_RESULT_HELP:
if ((qualifier & (1 << 7)) == 0) {
ofono_error("Help requested but not available");
send_simple_response(stk,
STK_RESULT_TYPE_USER_TERMINATED);
break;
}
send_simple_response(stk, STK_RESULT_TYPE_HELP_REQUESTED);
break;
case STK_AGENT_RESULT_TERMINATE:
default:
send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
break;
}
}
static void request_key_cb(enum stk_agent_result result, char *string,
void *user_data)
{
struct ofono_stk *stk = user_data;
static struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE };
struct stk_command_get_inkey *cmd = &stk->pending_cmd->get_inkey;
uint8_t qualifier = stk->pending_cmd->qualifier;
struct stk_response rsp;
switch (result) {
case STK_AGENT_RESULT_OK:
memset(&rsp, 0, sizeof(rsp));
rsp.result.type = STK_RESULT_TYPE_SUCCESS;
rsp.get_inkey.text.text = string;
if (cmd->duration.interval) {
rsp.get_inkey.duration.unit = cmd->duration.unit;
set_get_inkey_duration(&rsp.get_inkey.duration,
&stk->get_inkey_start_ts);
}
if (stk_respond(stk, &rsp, stk_command_cb))
stk_command_cb(&error, stk);
break;
case STK_AGENT_RESULT_BACK:
send_simple_response(stk, STK_RESULT_TYPE_GO_BACK);
break;
case STK_AGENT_RESULT_TIMEOUT:
send_simple_response(stk, STK_RESULT_TYPE_NO_RESPONSE);
break;
case STK_AGENT_RESULT_HELP:
if ((qualifier & (1 << 7)) == 0) {
ofono_error("Help requested but not available");
send_simple_response(stk,
STK_RESULT_TYPE_USER_TERMINATED);
break;
}
send_simple_response(stk, STK_RESULT_TYPE_HELP_REQUESTED);
break;
case STK_AGENT_RESULT_TERMINATE:
default:
send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
break;
}
}
static gboolean handle_command_get_inkey(const struct stk_command *cmd,
struct stk_response *rsp,
struct ofono_stk *stk)
{
int timeout = stk->timeout * 1000;
const struct stk_command_get_inkey *gi = &cmd->get_inkey;
uint8_t qualifier = stk->pending_cmd->qualifier;
gboolean alphabet = (qualifier & (1 << 0)) != 0;
gboolean ucs2 = (qualifier & (1 << 1)) != 0;
gboolean yesno = (qualifier & (1 << 2)) != 0;
/*
* Note: immediate response and help parameter values are not
* provided by current api.
*/
uint8_t icon_id = 0;
int err;
if (gi->duration.interval) {
timeout = gi->duration.interval;
switch (gi->duration.unit) {
case STK_DURATION_TYPE_MINUTES:
timeout *= 60;
case STK_DURATION_TYPE_SECONDS:
timeout *= 10;
case STK_DURATION_TYPE_SECOND_TENTHS:
timeout *= 100;
}
}
gettimeofday(&stk->get_inkey_start_ts, NULL);
stk->cancel_cmd = stk_request_cancel;
if (yesno)
err = stk_agent_request_confirmation(stk->current_agent,
gi->text, icon_id,
request_confirmation_cb,
stk, NULL, timeout);
else if (alphabet)
err = stk_agent_request_key(stk->current_agent, gi->text,
icon_id, ucs2, request_key_cb,
stk, NULL, timeout);
else
err = stk_agent_request_digit(stk->current_agent, gi->text,
icon_id, request_key_cb,
stk, NULL, timeout);
if (err < 0) {
/*
* We most likely got an out of memory error, tell SIM
* to retry
*/
rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
return TRUE;
}
return FALSE;
}
static void stk_proactive_command_cancel(struct ofono_stk *stk)
{
if (stk->immediate_response)
@ -1268,6 +1463,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
&rsp, stk);
break;
case STK_COMMAND_TYPE_GET_INKEY:
respond = handle_command_get_inkey(stk->pending_cmd,
&rsp, stk);
break;
default:
rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
break;