On 25 November 2010 13:29, Yang Gu <[email protected]> wrote:
> ---
>  src/smsutil.c  |    6 +-
>  src/stk.c      |  113 +++++++++++++++++++++++++++++++++++++++++
>  src/stkagent.c |  153 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/stkagent.h |   14 +++++
>  src/stkutil.c  |    2 +-
>  5 files changed, 284 insertions(+), 4 deletions(-)
>
> diff --git a/src/smsutil.c b/src/smsutil.c
> index e6dbf5f..5394817 100644
> --- a/src/smsutil.c
> +++ b/src/smsutil.c
> @@ -324,10 +324,10 @@ gboolean sms_encode_scts(const struct sms_scts *in, 
> unsigned char *pdu,
>        if (in->year > 99)
>                return FALSE;
>
> -       if (in->month > 12)
> +       if (in->month > 12 || in->month == 0)
>                return FALSE;
>
> -       if (in->day > 31)
> +       if (in->day > 31 || in->day == 0)
>                return FALSE;
>
>        if (in->hour > 23)
> @@ -339,7 +339,7 @@ gboolean sms_encode_scts(const struct sms_scts *in, 
> unsigned char *pdu,
>        if (in->second > 59)
>                return FALSE;
>
> -       if ((in->timezone > 12*4-1) || (in->timezone < -(12*4-1)))
> +       if ((in->timezone > 12*4) || (in->timezone < -(12*4-1)))

Please ignore my comment about the range in the other, because you
already fixed this :)

>                return FALSE;
>
>        pdu = pdu + *offset;
> diff --git a/src/stk.c b/src/stk.c
> index ac2e646..1f3817f 100644
> --- a/src/stk.c
> +++ b/src/stk.c
> @@ -1992,6 +1992,114 @@ static gboolean handle_command_refresh(const struct 
> stk_command *cmd,
>        return TRUE;
>  }
>
> +static void request_time_cb(enum stk_agent_result result, unsigned char year,
> +                               unsigned char month, unsigned char day,
> +                               unsigned char hour, unsigned char minute,
> +                               unsigned char second, char timezone,
> +                               void *user_data)
> +{
> +       struct ofono_stk *stk = user_data;
> +       static struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE 
> };
> +       struct stk_response rsp;
> +
> +       stk->respond_on_exit = FALSE;
> +
> +       switch (result) {
> +       case STK_AGENT_RESULT_OK:
> +               memset(&rsp, 0, sizeof(rsp));
> +
> +               rsp.result.type = STK_RESULT_TYPE_SUCCESS;
> +               rsp.provide_local_info.datetime.year = year;
> +               rsp.provide_local_info.datetime.month = month;
> +               rsp.provide_local_info.datetime.day = day;
> +               rsp.provide_local_info.datetime.hour = hour;
> +               rsp.provide_local_info.datetime.minute = minute;
> +               rsp.provide_local_info.datetime.second = second;
> +               rsp.provide_local_info.datetime.timezone = timezone;
> +
> +               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;

Note that "Backward move", "No reponse" and "User terminated" are not
allowed responses for Provide Local Info in TS102.223 6.11.

> +
> +       case STK_AGENT_RESULT_TIMEOUT:
> +               send_simple_response(stk, STK_RESULT_TYPE_NO_RESPONSE);
> +               break;
> +
> +       case STK_AGENT_RESULT_TERMINATE:
> +               send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
> +               break;
> +       }
> +}
> +
> +static void request_lang_cb(enum stk_agent_result result, char *lang,
> +                               void *user_data)
> +{
> +       struct ofono_stk *stk = user_data;
> +       static struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE 
> };
> +       struct stk_response rsp;
> +
> +       stk->respond_on_exit = FALSE;
> +
> +       switch (result) {
> +       case STK_AGENT_RESULT_OK:
> +               memset(&rsp, 0, sizeof(rsp));
> +
> +               rsp.result.type = STK_RESULT_TYPE_SUCCESS;
> +               rsp.provide_local_info.language = lang;
> +
> +               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_TERMINATE:
> +               send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
> +               break;
> +       }
> +}
> +
> +static gboolean handle_command_provide_local_info(const struct stk_command 
> *cmd,
> +                               struct stk_response *rsp, struct ofono_stk 
> *stk)
> +{
> +       int timeout = stk->timeout * 1000;
> +       int err;
> +
> +       switch (cmd->qualifier) {
> +       case 3:
> +               DBG("Date, time and time zone");
> +               err = stk_agent_request_time(stk->current_agent,
> +                                               request_time_cb,
> +                                               stk, NULL, timeout);
> +               return FALSE;
> +
> +       case 4:
> +               DBG("Language setting");
> +               err = stk_agent_request_lang(stk->current_agent,
> +                                               request_lang_cb,
> +                                               stk, NULL, timeout);
> +               return FALSE;
> +
> +       default:
> +               ofono_info("Unsupported Provide Local Info qualifier: %d",
> +                               cmd->qualifier);
> +               rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +               return TRUE;
> +       }
> +}
> +
>  static void send_dtmf_cancel(struct ofono_stk *stk)
>  {
>        struct ofono_voicecall *vc = NULL;
> @@ -2424,6 +2532,11 @@ void ofono_stk_proactive_command_notify(struct 
> ofono_stk *stk,
>                                                        &rsp, stk);
>                break;
>
> +       case STK_COMMAND_TYPE_PROVIDE_LOCAL_INFO:
> +               respond = handle_command_provide_local_info(stk->pending_cmd,
> +                                                               &rsp, stk);
> +               break;
> +
>        case STK_COMMAND_TYPE_SEND_DTMF:
>                respond = handle_command_send_dtmf(stk->pending_cmd,
>                                                        &rsp, stk);
> diff --git a/src/stkagent.c b/src/stkagent.c
> index 5cf83e4..78620d5 100644
> --- a/src/stkagent.c
> +++ b/src/stkagent.c
> @@ -956,3 +956,156 @@ int stk_agent_loop_tone(struct stk_agent *agent, const 
> char *text,
>
>        return 0;
>  }
> +
> +static void get_time_cb(DBusPendingCall *call, void *data)
> +{
> +       struct stk_agent *agent = data;
> +       stk_agent_time_cb cb = agent->user_cb;
> +       DBusMessage *reply = dbus_pending_call_steal_reply(call);
> +       enum stk_agent_result result;
> +       gboolean remove_agent;
> +       int year_dbus;
> +       unsigned char year;
> +       unsigned char month;
> +       unsigned char day;
> +       unsigned char hour;
> +       unsigned char minute;
> +       unsigned char second;
> +       int timezone_dbus;
> +       char timezone;

I think you need to use "signed char" to achieve the same type as
int8_t/guin8 because the sign of "char" depends on the ABI.

> +
> +       if (check_error(agent, reply,
> +                       ALLOWED_ERROR_GO_BACK | ALLOWED_ERROR_TERMINATE,
> +                       &result) == -EINVAL) {

Go back and Terminate are not allowed for this command. (same comment as above)

> +               remove_agent = TRUE;
> +               goto error;
> +       }
> +
> +       if (result != STK_AGENT_RESULT_OK) {
> +               cb(result, 0, 0, 0, 0, 0, 0, 0xFF, agent->user_data);
> +               goto done;
> +       }
> +
> +       if (dbus_message_get_args(reply, NULL,
> +                                       DBUS_TYPE_INT32, &year_dbus,
> +                                       DBUS_TYPE_BYTE, &month,
> +                                       DBUS_TYPE_BYTE, &day,
> +                                       DBUS_TYPE_BYTE, &hour,
> +                                       DBUS_TYPE_BYTE, &minute,
> +                                       DBUS_TYPE_BYTE, &second,
> +                                       DBUS_TYPE_INT32, &timezone_dbus,
> +                                       DBUS_TYPE_INVALID) == FALSE) {
> +               ofono_error("Can't parse the reply to RequestTime()");
> +               remove_agent = TRUE;
> +               goto error;
> +       }
> +
> +       if (year_dbus < 1900) {
> +               ofono_error("Invalid year");
> +               remove_agent = TRUE;
> +               goto error;
> +       }

I believe the range is actually 1970-2069 or similar (only values 0-99
in the sms header are allowed)

> +
> +       if (year_dbus >= 2000)
> +               year = year_dbus - 2000;
> +       else
> +               year = year_dbus - 1900;
> +
> +       timezone = timezone_dbus;
> +
> +       cb(result, year, month, day, hour, minute, second, timezone,
> +                                                       agent->user_data);
> +
> +       CALLBACK_END();
> +}
> +
> +int stk_agent_request_time(struct stk_agent *agent, stk_agent_time_cb cb,
> +                               void *user_data, ofono_destroy_func destroy,
> +                               int timeout)
> +{
> +       DBusConnection *conn = ofono_dbus_get_connection();
> +
> +       agent->msg = dbus_message_new_method_call(agent->bus, agent->path,
> +                                                       
> OFONO_SIM_APP_INTERFACE,
> +                                                       "RequestTime");
> +       if (agent->msg == NULL)
> +               return -ENOMEM;
> +
> +       dbus_message_append_args(agent->msg, DBUS_TYPE_INVALID);
> +
> +       if (dbus_connection_send_with_reply(conn, agent->msg, &agent->call,
> +                                               timeout) == FALSE ||
> +                       agent->call == NULL)
> +               return -EIO;
> +
> +       agent->user_cb = cb;
> +       agent->user_data = user_data;
> +       agent->user_destroy = destroy;
> +
> +       dbus_pending_call_set_notify(agent->call, get_time_cb, agent, NULL);
> +
> +       return 0;
> +}
> +
> +static void get_lang_cb(DBusPendingCall *call, void *data)
> +{
> +       struct stk_agent *agent = data;
> +       stk_agent_string_cb cb = agent->user_cb;
> +       DBusMessage *reply = dbus_pending_call_steal_reply(call);
> +       enum stk_agent_result result;
> +       gboolean remove_agent;
> +       char *lang;
> +
> +       if (check_error(agent, reply,
> +                       ALLOWED_ERROR_GO_BACK | ALLOWED_ERROR_TERMINATE,
> +                       &result) == -EINVAL) {
> +               remove_agent = TRUE;
> +               goto error;
> +       }
> +
> +       if (result != STK_AGENT_RESULT_OK) {
> +               cb(result, NULL, agent->user_data);
> +               goto done;
> +       }
> +
> +       if (dbus_message_get_args(reply, NULL,
> +                                       DBUS_TYPE_STRING, &lang,
> +                                       DBUS_TYPE_INVALID) == FALSE ||
> +                       strlen(lang) != 2) {
> +               ofono_error("Can't parse the reply to RequestLanguage()");
> +               remove_agent = TRUE;
> +               goto error;
> +       }
> +
> +       cb(result, lang, agent->user_data);
> +
> +       CALLBACK_END();
> +}
> +
> +int stk_agent_request_lang(struct stk_agent *agent, stk_agent_string_cb cb,
> +                               void *user_data, ofono_destroy_func destroy,
> +                               int timeout)
> +{
> +       DBusConnection *conn = ofono_dbus_get_connection();
> +
> +       agent->msg = dbus_message_new_method_call(agent->bus, agent->path,
> +                                                       
> OFONO_SIM_APP_INTERFACE,
> +                                                       "RequestLanguage");
> +       if (agent->msg == NULL)
> +               return -ENOMEM;
> +
> +       dbus_message_append_args(agent->msg, DBUS_TYPE_INVALID);
> +
> +       if (dbus_connection_send_with_reply(conn, agent->msg, &agent->call,
> +                                               timeout) == FALSE ||
> +                       agent->call == NULL)
> +               return -EIO;
> +
> +       agent->user_cb = cb;
> +       agent->user_data = user_data;
> +       agent->user_destroy = destroy;
> +
> +       dbus_pending_call_set_notify(agent->call, get_lang_cb, agent, NULL);
> +
> +       return 0;
> +}
> diff --git a/src/stkagent.h b/src/stkagent.h
> index c8e1886..a60cf23 100644
> --- a/src/stkagent.h
> +++ b/src/stkagent.h
> @@ -59,6 +59,12 @@ typedef void (*stk_agent_string_cb)(enum stk_agent_result 
> result,
>  typedef void (*stk_agent_tone_cb)(enum stk_agent_result result,
>                                                void *user_data);
>
> +typedef void (*stk_agent_time_cb)(enum stk_agent_result result,
> +                               unsigned char year, unsigned char month,
> +                               unsigned char day, unsigned char hour,
> +                               unsigned char minute, unsigned char second,
> +                               char timezone, void *user_data);
> +
>  struct stk_agent *stk_agent_new(const char *path, const char *sender,
>                                        ofono_bool_t remove_on_terminate);
>
> @@ -136,3 +142,11 @@ int stk_agent_loop_tone(struct stk_agent *agent, const 
> char *text,
>
>  void append_menu_items_variant(DBusMessageIter *iter,
>                                const struct stk_menu_item *items);
> +
> +int stk_agent_request_time(struct stk_agent *agent, stk_agent_time_cb cb,
> +                       void *user_data, ofono_destroy_func destroy,
> +                       int timeout);
> +
> +int stk_agent_request_lang(struct stk_agent *agent, stk_agent_string_cb cb,
> +                       void *user_data, ofono_destroy_func destroy,
> +                       int timeout);
> diff --git a/src/stkutil.c b/src/stkutil.c
> index 377ceff..48ce93b 100644
> --- a/src/stkutil.c
> +++ b/src/stkutil.c
> @@ -4553,7 +4553,7 @@ static gboolean build_dataobj_datetime_timezone(struct 
> stk_tlv_builder *tlv,
>                return TRUE;
>
>        /* Time zone information is optional */
> -       if (scts->timezone == (gint8) 0xff) {
> +       if (scts->timezone == -48) {

Ah, -48 is also a good value :)

But wouldn't the parser also need to translate 0xff into -48?

Best regards
_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to