mirror of git://git.sysmocom.de/ofono
stk: Handle the Get Inkey proactive command
This commit is contained in:
parent
939fc1273c
commit
ed169aa02f
200
src/stk.c
200
src/stk.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue