Hi Andreas,
2011/2/15 Andreas Westin <andreas.westin(a)stericsson.com>:
From: Jessica Nilsson <jessica.j.nilsson(a)stericsson.com>
---
drivers/isimodem/call-settings.c | 697 +++++++++++++++++++++++++++++++++++++-
drivers/isimodem/call.h | 9 +
drivers/isimodem/debug.c | 4 +
drivers/isimodem/ss.h | 22 ++
4 files changed, 714 insertions(+), 18 deletions(-)
diff --git a/drivers/isimodem/call-settings.c b/drivers/isimodem/call-settings.c
index 89270e9..7a6bedf 100644
--- a/drivers/isimodem/call-settings.c
+++ b/drivers/isimodem/call-settings.c
@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) ST-Ericsson SA 2011.
*
* 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
@@ -43,10 +44,15 @@
#include "ss.h"
#include "debug.h"
+#define CLIP_ETC
+
I don't see this used anywhere in the code.
struct settings_data {
GIsiClient *client;
};
+#define content_size 40
+static char content[content_size] = {0};
+
(snip)
+static int set_clir_status(const char *value)
+{
+ DBG("Setting CLIR status to %s", value);
+ strncpy(content, value, content_size);
+ content[content_size-1] = 0;
+ return EXIT_SUCCESS;
+}
+
+static int get_clir_status(void)
+{
+ DBG("Getting CLIR status %s", content);
+
+ if (!strcmp(content, "OFONO_CLIR_OPTION_INVOCATION"))
+ return OFONO_CLIR_OPTION_INVOCATION;
+
+ if (!strcmp(content, "OFONO_CLIR_OPTION_SUPPRESSION"))
+ return OFONO_CLIR_OPTION_SUPPRESSION;
+
+ return OFONO_CLIR_OPTION_DEFAULT;
+}
I don't understand this part. Why is 'content' a static buffer, and
why is strncpy() used? All I see are const strings copied there.
Also, if the getter anyway returns an int, why not store an int there
in the first place? Could it also be part of the call-settings driver
data?
+static void clir_set_cb(const GIsiMessage *msg, void *data)
+{
+ GIsiSubBlockIter iter, iter_info;
+ struct isi_cb_data *cbd = data;
+ ofono_call_settings_set_cb_t cb = cbd->cb;
+ gint override = OFONO_CLIR_OPTION_DEFAULT;
+ gint network = CLIR_STATUS_UNKNOWN;
+ uint8_t service;
+
+ if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP))
+ goto error;
+
+ if (!g_isi_msg_data_get_byte(msg, 0, &service) ||
+ service != SS_INTERROGATION)
+ goto error;
+
+ for (g_isi_sb_iter_init(&iter, msg, 6);
g_isi_sb_iter_is_valid(&iter);
g_isi_sb_iter_next(&iter)) {
+ DBG("Sub-block %s",
+ ss_subblock_name(g_isi_sb_iter_get_id(&iter)));
- if (g_isi_sb_iter_get_id(&iter) != SS_GSM_BSC_INFO)
- continue;
+ switch (g_isi_sb_iter_get_id(&iter)) {
+ case SS_STATUS_RESULT: {
+ guint8 ss_status;
+
+ if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2))
+ goto error;
+
+ DBG("SS_STATUS_RESULT=%d", ss_status);
+
+ if (!(ss_status & SS_GSM_PROVISIONED))
+ network = CLIR_STATUS_NOT_PROVISIONED;
+ }
+ break;
+ case SS_GSM_ADDITIONAL_INFO:
+ break;
+ case SS_GSM_GENERIC_SERVICE_INFO: {
+ guint8 ss_status = 0;
+ guint8 clir_option = 0;
+ void *info = NULL;
+ GIsiMessage info_msg;
+
+ if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2))
+ goto error;
+
+ if (!(ss_status & SS_GSM_PROVISIONED))
+ network = CLIR_STATUS_NOT_PROVISIONED;
+
+ if (!g_isi_sb_iter_get_data(&iter, &info, 4))
+ goto error;
+
+ info_msg.addr = NULL;
+ info_msg.error = 0;
+ /*
+ * GIsiMessage function adds 2 to data pointer and
+ * removes 2 from len
+ */
+ info_msg.data = info - 2;
+ info_msg.len = msg->len - 6 + 2;
+
+ for (g_isi_sb_iter_init(&iter_info, &info_msg, 0);
+ g_isi_sb_iter_is_valid(&iter_info);
+ g_isi_sb_iter_next(&iter_info)) {
+ DBG("Sub-block %s",
+ ss_subblock_name(
+ g_isi_sb_iter_get_id(&iter_info)));
+
+ switch (g_isi_sb_iter_get_id(&iter_info)) {
+ case SS_GSM_CLIR_INFO: {
+ if (!g_isi_sb_iter_get_byte(&iter_info,
+ &clir_option, 2))
+ goto error;
+ }
+ break;
+ }
+
+ DBG("SS_STATUS_RESULT=%d, CLIR_OPTION=%d",
+ ss_status, clir_option);
+ }
+
+ if (network != CLIR_STATUS_NOT_PROVISIONED) {
+ int result;
+ DBG("CLIR set successfully.");
+ result = set_clir_status(
+ "OFONO_CLIR_OPTION_INVOCATION");
+
+ if (result == EXIT_FAILURE)
+ goto error;
+ } else {
+ DBG("CLIR option not supported by network "
+ "provider.");
+ }
+ }
+ break;
+ default:
+ DBG("Skipping sub-block: %s (%zd bytes)",
+ ss_subblock_name(g_isi_sb_iter_get_id(&iter)),
+ g_isi_sb_iter_get_len(&iter));
+ break;
+ }
+ }
- if (!decode_gsm_bsc_info(&iter, &mask))
+ DBG("override=%d, network=%d\n", override, network);
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
+ return;
+error:
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+}
This function is really hard to follow. I would consider breaking it
up so that each sub-block decoder is a separate static function of its
own.
+static void isi_clir_set(struct ofono_call_settings *cs,
+ int mode,
+ ofono_call_settings_set_cb_t cb,
+ void *data)
+{
+ struct settings_data *sd = ofono_call_settings_get_data(cs);
+ struct isi_cb_data *cbd = isi_cb_data_new(cs, cb, data);
+ int result = 0;
+ /*
+ * CLIR cannot be activated in Network, but we can override it
+ * using local settings - 3GPP TS 24.081 Chapter 2.5
+ */
+
+ switch (mode) {
+ case(OFONO_CLIR_OPTION_DEFAULT):
+ result = set_clir_status("OFONO_CLIR_OPTION_DEFAULT");
+ break;
Indentation is broken here.
+ /* CLIR enabled (number not shown) */
+ case(OFONO_CLIR_OPTION_INVOCATION): {
+ /*
+ * We send interrogation request to check if Network
+ * has CLIR option provisioned.
+ */
+ unsigned char msg[] = {
+ SS_SERVICE_REQ,
+ SS_INTERROGATION,
+ SS_ALL_TELE_AND_BEARER,
+ SS_GSM_CLIR >> 8, /* Supplementary services */
+ SS_GSM_CLIR & 0xFF, /* code */
+ SS_SEND_ADDITIONAL_INFO,
+ 0 /* Subblock count */
+ };
+
+ DBG("Attempting to set the CLIR - checking Network Settings");
+
+ if (cbd == NULL)
+ goto error;
+
+ if (g_isi_client_send(sd->client, msg, sizeof(msg),
+ clir_set_cb, cbd, g_free))
+
+ return;
+ else
goto error;
+ }
+ break;
+ case(OFONO_CLIR_OPTION_SUPPRESSION): /* CLIR disabled (number shown) */
+ result = set_clir_status("OFONO_CLIR_OPTION_SUPPRESSION");
+ break;
+ default:
+ DBG("CLIR mode not supported %d", mode);
+ break;
+ }
+
+ if (result == EXIT_FAILURE)
+ goto error;
+
+ DBG("CLIR set to mode: %d", mode);
+ CALLBACK_WITH_SUCCESS(cb, data);
+ goto out;
+error:
+ CALLBACK_WITH_FAILURE(cb, data);
+out:
+ g_free(cbd);
+ return;
+}
+
+static void clir_query_cb(const GIsiMessage *msg, void *data)
+{
+ GIsiSubBlockIter iter, iter_info;
+ struct isi_cb_data *cbd = data;
+ ofono_call_settings_clir_cb_t cb = cbd->cb;
+ uint8_t service;
+ gint override = OFONO_CLIR_OPTION_DEFAULT;
+ gint network = CLIR_STATUS_UNKNOWN;
+
+
+ if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP))
+ goto error;
+
+ if (!g_isi_msg_data_get_byte(msg, 0, &service) ||
+ service != SS_INTERROGATION)
+ goto error;
+
+ for (g_isi_sb_iter_init(&iter, msg, 6);
+ g_isi_sb_iter_is_valid(&iter);
+ g_isi_sb_iter_next(&iter)) {
+ DBG("Sub-block %s",
+ ss_subblock_name(g_isi_sb_iter_get_id(&iter)));
+ switch (g_isi_sb_iter_get_id(&iter)) {
+ case SS_STATUS_RESULT: {
+ guint8 ss_status;
+
+ if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2))
+ goto error;
+
+ DBG("SS_STATUS_RESULT=%d", ss_status);
+
+ if (!(ss_status & SS_GSM_PROVISIONED))
+ network = CLIR_STATUS_NOT_PROVISIONED;
+ }
+ break;
Indentation is broken here. Why is the break outside the brackets anyway?
+ case SS_GSM_ADDITIONAL_INFO:
+ break;
+ case SS_GSM_GENERIC_SERVICE_INFO: {
+ guint8 ss_status = 0;
+ guint8 clir_option = 0;
+ void *info = NULL;
+ GIsiMessage info_msg;
+
+ if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2))
+ goto error;
+
+ if (!(ss_status & SS_GSM_PROVISIONED))
+ network = CLIR_STATUS_NOT_PROVISIONED;
+
+ if (!g_isi_sb_iter_get_data(&iter, &info, 4))
+ goto error;
+
+ info_msg.addr = NULL;
+ info_msg.error = 0;
+ /* GIsiMessage function adds 2 to data pointer and
+ * removes 2 from len */
+ info_msg.data = info - 2;
+ info_msg.len = msg->len - 6 + 2;
+
+ for (g_isi_sb_iter_init(&iter_info, &info_msg, 0);
+ g_isi_sb_iter_is_valid(&iter_info);
+ g_isi_sb_iter_next(&iter_info)) {
+ uint8_t id = g_isi_sb_iter_get_id(&iter_info);
+ DBG("Sub-sub-block %d", id);
+
+ switch (id) {
+ case SS_GSM_CLIR_INFO: {
+ if (!g_isi_sb_iter_get_byte(&iter_info,
+ &clir_option, 2))
+ goto error;
+ break;
+ }
+ default:
+ break;
+ }
+
+ DBG("SS_STATUS_RESULT=%d, CLIR_OPTION=%d",
+ ss_status, clir_option);
+ }
+
+ if (network != CLIR_STATUS_NOT_PROVISIONED) {
+ switch (clir_option) {
+ case SS_GSM_CLI_PERMANENT:
+ network =
+ CLIR_STATUS_PROVISIONED_PERMANENT;
+ break;
+ case SS_GSM_DEFAULT_RESTRICTED:
+ break;
+ case SS_GSM_CLI_DEFAULT_ALLOWED:
+ network =
+ CLIR_STATUS_TEMPORARY_ALLOWED;
+ break;
+ case SS_GSM_OVERRIDE_ENABLED:
+ override =
+ OFONO_CLIR_OPTION_SUPPRESSION;
+ break;
+ case SS_GSM_OVERRIDE_DISABLED:
+ override =
+ OFONO_CLIR_OPTION_INVOCATION;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ DBG("Skipping sub-block: %s (%zd bytes)",
+ ss_subblock_name(g_isi_sb_iter_get_id(&iter)),
+ g_isi_sb_iter_get_len(&iter));
+ break;
+ }
+ }
+ /*
+ * CLIR cannot be activated,registrated in Network, but we can override
+ * it using local settings - 33GPP TS 24.081 Chapter 2.5
+ * we have to read status and pass override parameter to Ofono
+ */
+
+ if (network != CLIR_STATUS_NOT_PROVISIONED) {
+ override = get_clir_status();
+ DBG("CLIR mode queried %d\n", override);
+ }
+
+ DBG("override=%d, network=%d\n", override, network);
+ CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data);
+ return;
+error:
+ CALLBACK_WITH_FAILURE(cb, override, network, cbd->data);
+}
Same as above; this function needs some refactoring to split the
decoding up into several functions.
Cheers,
Aki