Add basic support for USAT/CAT proactive commands
authorDenis Kenzior <denkenz@gmail.com>
Tue, 23 Feb 2010 23:10:26 +0000 (17:10 -0600)
committerDenis Kenzior <denkenz@gmail.com>
Tue, 23 Feb 2010 23:10:26 +0000 (17:10 -0600)
Only display_text with mandatory fields is currently supported.

src/stkutil.c
src/stkutil.h

index 497ad5b..bfe2967 100644 (file)
 
 #include <ofono/types.h>
 #include "stkutil.h"
+#include "smsutil.h"
+#include "simutil.h"
+#include "util.h"
+
+static gboolean parse_dataobj_text(struct stk_command *command,
+                                       struct comprehension_tlv_iter *iter)
+{
+       unsigned int len;
+
+       if (comprehension_tlv_iter_next(iter) != TRUE)
+               return FALSE;
+
+       if (comprehension_tlv_iter_get_tag(iter) !=
+                       STK_DATA_OBJECT_TYPE_TEXT)
+               return FALSE;
+
+       len = comprehension_tlv_iter_get_length(iter);
+
+       /* DCS followed by some text, cannot be 1 */
+       if (len == 1)
+               return FALSE;
+
+       if (len > 0) {
+               const unsigned char *data =
+                       comprehension_tlv_iter_get_data(iter);
+               unsigned char dcs = data[0];
+               char *utf8;
+
+               switch (dcs) {
+               case 0x00:
+               {
+                       long written;
+                       unsigned long max_to_unpack = (len - 1) * 8 / 7;
+                       unsigned char *unpacked = unpack_7bit(data + 1, len - 1,
+                                                               0, FALSE,
+                                                               max_to_unpack,
+                                                               &written, 0);
+                       if (unpacked == NULL)
+                               return FALSE;
+
+                       utf8 = convert_gsm_to_utf8(unpacked, written,
+                                                       NULL, NULL, 0);
+                       g_free(unpacked);
+                       break;
+               }
+               case 0x04:
+                       utf8 = convert_gsm_to_utf8(data + 1, len - 1,
+                                                       NULL, NULL, 0);
+                       break;
+               case 0x08:
+                       utf8 = g_convert((const gchar *) data + 1, len - 1,
+                                               "UTF-8//TRANSLIT", "UCS-2BE",
+                                               NULL, NULL, NULL);
+                       break;
+               default:
+                       return FALSE;;
+               }
+
+               if (utf8 == NULL)
+                       return FALSE;
+
+               command->display_text.text = utf8;
+       } else
+               command->display_text.text = NULL;
+
+       return TRUE;
+}
+
+static void destroy_display_text(struct stk_command *command)
+{
+       g_free(command->display_text.text);
+}
+
+static gboolean parse_display_text(struct stk_command *command,
+                                       struct comprehension_tlv_iter *iter)
+{
+       if (parse_dataobj_text(command, iter) == FALSE)
+               return FALSE;
+
+       command->destructor = destroy_display_text;
+
+       return TRUE;
+}
+
+struct stk_command *stk_command_new_from_pdu(const unsigned char *pdu,
+                                               unsigned int len)
+{
+       struct ber_tlv_iter ber;
+       struct comprehension_tlv_iter iter;
+       const unsigned char *data;
+       struct stk_command *command;
+       gboolean ok;
+
+       ber_tlv_iter_init(&ber, pdu, len);
+
+       if (ber_tlv_iter_next(&ber) != TRUE)
+               return NULL;
+
+       /* We should be wrapped in a Proactive UICC Command Tag 0xD0 */
+       if (ber_tlv_iter_get_short_tag(&ber) != 0xD0)
+               return NULL;
+
+       ber_tlv_iter_recurse_comprehension(&ber, &iter);
+
+       /*
+        * Now parse actual command details, they come in order with
+        * Command Details TLV first, followed by Device Identities TLV
+        */
+       if (comprehension_tlv_iter_next(&iter) != TRUE)
+               return NULL;
+
+       if (comprehension_tlv_iter_get_tag(&iter) !=
+                       STK_DATA_OBJECT_TYPE_COMMAND_DETAILS)
+               return NULL;
+
+       if (comprehension_tlv_iter_get_length(&iter) != 0x03)
+               return NULL;
+
+       data = comprehension_tlv_iter_get_data(&iter);
+
+       command = g_new0(struct stk_command, 1);
+
+       command->number = data[0];
+       command->type = data[1];
+       command->qualifier = data[2];
+
+       if (comprehension_tlv_iter_next(&iter) != TRUE)
+               goto fail;
+
+       if (comprehension_tlv_iter_get_tag(&iter) !=
+                       STK_DATA_OBJECT_TYPE_DEVICE_IDENTITIES)
+               goto fail;
+
+       if (comprehension_tlv_iter_get_length(&iter) != 0x02)
+               goto fail;
+
+       data = comprehension_tlv_iter_get_data(&iter);
+
+       command->src = data[0];
+       command->dst = data[1];
+
+       switch (command->type) {
+       case STK_COMMAND_TYPE_DISPLAY_TEXT:
+               ok = parse_display_text(command, &iter);
+               break;
+       default:
+               ok = FALSE;
+               break;
+       };
+
+       if (ok)
+               return command;
+
+fail:
+       if (command->destructor)
+               command->destructor(command);
+
+       g_free(command);
+
+       return NULL;
+}
+
+void stk_command_free(struct stk_command *command)
+{
+       if (command->destructor)
+               command->destructor(command);
+
+       g_free(command);
+}
index 7e9ad86..9fd7146 100644 (file)
@@ -81,7 +81,7 @@ enum stk_command_type {
 
 enum stk_data_object_type {
        STK_DATA_OBJECT_TYPE_COMMAND_DETAILS = 0x01,
-       STK_DATA_OBJECT_TYPE_DEVICE_IDENTITY = 0x02,
+       STK_DATA_OBJECT_TYPE_DEVICE_IDENTITIES = 0x02,
        STK_DATA_OBJECT_TYPE_RESULT = 0x03,
        STK_DATA_OBJECT_TYPE_DURATION = 0x04,
        STK_DATA_OBJECT_TYPE_ALPHA_IDENTIFIER = 0x05,
@@ -184,3 +184,28 @@ enum stk_device_identity_type {
        STK_DEVICE_IDENTITY_TYPE_TERMINAL = 0x82,
        STK_DEVICE_IDENTITY_TYPE_NETWORK = 0x83,
 };
+
+struct stk_command_display_text {
+       char *text;
+       unsigned char icon_id;
+       unsigned char icon_qualifier;
+       ofono_bool_t immediate_response;
+};
+
+struct stk_command {
+       unsigned char number;
+       unsigned char type;
+       unsigned char qualifier;
+       enum stk_device_identity_type src;
+       enum stk_device_identity_type dst;
+
+       union {
+               struct stk_command_display_text display_text;
+       };
+
+       void (*destructor)(struct stk_command *command);
+};
+
+struct stk_command *stk_command_new_from_pdu(const unsigned char *pdu,
+                                               unsigned int len);
+void stk_command_free(struct stk_command *command);