---
 gatchat/gatchat.c |  236 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 224 insertions(+), 12 deletions(-)

diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c
index e85d908..1527611 100644
--- a/gatchat/gatchat.c
+++ b/gatchat/gatchat.c
@@ -41,6 +41,8 @@
 struct at_chat;
 static void chat_wakeup_writer(struct at_chat *chat);
 
+static char *extract_line_with_crlf(struct at_chat *p,struct ring_buffer 
*rbuf);
+
 static const char *none_prefix[] = { NULL };
 
 struct at_command {
@@ -53,6 +55,7 @@ struct at_command {
        GAtNotifyFunc listing;
        gpointer user_data;
        GDestroyNotify notify;
+       gint cmd_len;
 };
 
 struct at_notify_node {
@@ -66,6 +69,7 @@ struct at_notify_node {
 struct at_notify {
        GSList *nodes;
        gboolean pdu;
+       GAtExpectMsgLenFunc expect_msglen_func;
 };
 
 struct at_chat {
@@ -208,7 +212,8 @@ static struct at_command *at_command_create(guint gid, 
const char *cmd,
        }
 
        c->cmd[len] = '\0';
-
+       /* Normal AT Command without length*/
+       c->cmd_len = -1;
        c->gid = gid;
        c->expect_pdu = expect_pdu;
        c->prefixes = prefixes;
@@ -330,6 +335,17 @@ static gboolean at_chat_match_notify(struct at_chat *chat, 
char *line)
                if (notify->pdu) {
                        chat->pdu_notify = line;
 
+                       /* Read expect message length
+                        * If length is -1, use original solution
+                        */
+                       if(notify->expect_msglen_func){
+                               int len = notify->expect_msglen_func(line);
+                               chat->syntax->expect_msg_len = len;
+                       }else{
+                               chat->syntax->expect_msg_len = -1;
+                       }
+
+
                        if (chat->syntax->set_hint)
                                chat->syntax->set_hint(chat->syntax,
                                                        G_AT_SYNTAX_EXPECT_PDU);
@@ -665,7 +681,14 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer 
user_data)
                        break;
 
                case G_AT_SYNTAX_RESULT_PDU:
-                       have_pdu(p, extract_line(p, rbuf));
+                       /* Modify support SMS Text Mode */
+                       if(p->syntax->expect_msg_len == -1){
+                               have_pdu(p, extract_line(p,rbuf));
+                       }else{
+                               have_pdu(p, extract_line_with_crlf(p,rbuf));
+                               /* Reset expect message len */
+                               p->syntax->expect_msg_len = -1;
+                       }
                        break;
 
                case G_AT_SYNTAX_RESULT_PROMPT:
@@ -733,7 +756,7 @@ static gboolean can_write_data(gpointer data)
        struct at_chat *chat = data;
        struct at_command *cmd;
        gsize bytes_written;
-       gsize towrite;
+       gsize towrite = 0;
        gsize len;
        char *cr;
        gboolean wakeup_first = FALSE;
@@ -747,7 +770,13 @@ static gboolean can_write_data(gpointer data)
        if (cmd == NULL)
                return FALSE;
 
-       len = strlen(cmd->cmd);
+       if(cmd->cmd_len == -1){
+               /* Normal AT Command length */
+               len = strlen(cmd->cmd);
+       }else{
+               /* SMS text mode AT command length */
+               len = cmd->cmd_len;
+       }
 
        /* For some reason write watcher fired, but we've already
         * written the entire command out to the io channel,
@@ -781,12 +810,26 @@ static gboolean can_write_data(gpointer data)
                                                wakeup_no_response, chat);
        }
 
-       towrite = len - chat->cmd_bytes_written;
-
-       cr = strchr(cmd->cmd + chat->cmd_bytes_written, '\r');
-
-       if (cr)
-               towrite = cr - (cmd->cmd + chat->cmd_bytes_written) + 1;
+       if (cmd->cmd_len == -1) {
+               /* Normal AT Command write */
+               towrite = len - chat->cmd_bytes_written;
+               cr = strchr(cmd->cmd + chat->cmd_bytes_written, '\r');
+               if (cr) {
+                       towrite = cr - (cmd->cmd + chat->cmd_bytes_written) + 1;
+               }
+       } else {
+               /* SMS text mode AT command write */
+               if(chat->cmd_bytes_written == 0){
+                       /* SMS text mode AT command write prefix */
+                       cr = strchr(cmd->cmd + chat->cmd_bytes_written, '\r');
+                       if (cr) {
+                               towrite = cr - (cmd->cmd + 
chat->cmd_bytes_written) + 1;
+                       }
+               }else{
+                       /* SMS text mode AT command write msg content */
+                       towrite = len - chat->cmd_bytes_written;
+               }
+       }
 
 #ifdef WRITE_SCHEDULER_DEBUG
        if (towrite > 5)
@@ -936,7 +979,8 @@ static guint at_chat_send_common(struct at_chat *chat, 
guint gid,
 
 static struct at_notify *at_notify_create(struct at_chat *chat,
                                                const char *prefix,
-                                               gboolean pdu)
+                                               gboolean pdu,
+                                               GAtExpectMsgLenFunc 
expect_msglen_func)
 {
        struct at_notify *notify;
        char *key;
@@ -953,6 +997,7 @@ static struct at_notify *at_notify_create(struct at_chat 
*chat,
        }
 
        notify->pdu = pdu;
+       notify->expect_msglen_func = expect_msglen_func;
 
        g_hash_table_insert(chat->notify_list, key, notify);
 
@@ -1040,7 +1085,7 @@ static guint at_chat_register(struct at_chat *chat, guint 
group,
        notify = g_hash_table_lookup(chat->notify_list, prefix);
 
        if (!notify)
-               notify = at_notify_create(chat, prefix, expect_pdu);
+               notify = at_notify_create(chat, prefix, expect_pdu, NULL);
 
        if (!notify || notify->pdu != expect_pdu)
                return 0;
@@ -1433,3 +1478,170 @@ gboolean g_at_chat_unregister_all(GAtChat *chat)
 
        return at_chat_unregister_group(chat->parent, chat->group);
 }
+
+/**
+ * Add extract function for reading line with CR and LF
+ * SMS response as Text Mode will use this function to extract line
+ */
+
+static char *extract_line_with_crlf(struct at_chat *p,struct ring_buffer *rbuf)
+{
+       unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
+       unsigned int pos = 0;
+       unsigned char *buf = ring_buffer_read_ptr(rbuf, pos);
+       int strip_front = 0;
+       int line_length = 0;
+       char *line;
+
+       while (pos < p->read_so_far) {
+
+               line_length += 1;
+               buf += 1;
+               pos += 1;
+
+               if (pos == wrap)
+                       buf = ring_buffer_read_ptr(rbuf, pos);
+       }
+
+       line = g_try_new(char, line_length + 1);
+
+       if (!line) {
+               ring_buffer_drain(rbuf, p->read_so_far);
+               return NULL;
+       }
+
+       ring_buffer_drain(rbuf, strip_front);
+       ring_buffer_read(rbuf, line, line_length);
+       ring_buffer_drain(rbuf, p->read_so_far - strip_front - line_length);
+
+       line[line_length] = '\0';
+
+       return line;
+}
+
+/**
+ * Create SMS text mode command with length
+ */
+static struct at_command *at_command_with_len_create(const char *cmd, int 
cmdlen,
+               const char **prefix_list, GAtResultFunc func, gpointer 
user_data,
+               GDestroyNotify notify) {
+       struct at_command *c;
+       gsize len;
+
+       char **prefixes = NULL;
+
+       if (prefix_list) {
+               int num_prefixes = 0;
+               int i;
+
+               while (prefix_list[num_prefixes])
+                       num_prefixes += 1;
+
+               prefixes = g_new(char *, num_prefixes + 1);
+
+               for (i = 0; i < num_prefixes; i++)
+                       prefixes[i] = strdup(prefix_list[i]);
+
+               prefixes[num_prefixes] = NULL;
+       }
+
+       c = g_try_new0(struct at_command, 1);
+
+       if (!c)
+               return 0;
+
+       len = cmdlen;
+       c->cmd = g_try_new(char, len+1);
+
+       if (!c->cmd) {
+               g_free(c);
+               return 0;
+       }
+
+       memcpy(c->cmd, cmd, len);
+
+       /* SMS text mode AT command with length*/
+       c->cmd[len] = '\0';
+       c->cmd_len = len;
+
+       c->expect_pdu = FALSE;
+       c->prefixes = prefixes;
+       c->callback = func;
+       c->listing = NULL;
+       c->user_data = user_data;
+       c->notify = notify;
+
+       return c;
+}
+/**
+ * Send AT command with length, such as SMS text mode which contains 0x00 or 
0x0A, 0x0D
+ */
+guint g_at_chat_send_with_len(GAtChat *child, const char *cmd, int cmdlen, 
const char **prefix_list,
+               GAtResultFunc func, gpointer user_data, GDestroyNotify notify) {
+
+       struct at_command *c;
+       struct at_chat *chat;
+       chat = child->parent;
+
+       if (chat == NULL || chat->command_queue == NULL)
+               return 0;
+
+       c = at_command_with_len_create(cmd, cmdlen, prefix_list, func, 
user_data, notify);
+
+       if (!c)
+               return 0;
+
+       c->id = chat->next_cmd_id++;
+
+       g_queue_push_tail(chat->command_queue, c);
+
+       if (g_queue_get_length(chat->command_queue) == 1)
+               chat_wakeup_writer(chat);
+
+       return c->id;
+}
+
+/**
+ * Modify from g_at_chat_register, add parameter expect_msglen_func
+ */
+guint g_at_chat_register_with_func(GAtChat *child, const char *prefix,
+                               GAtNotifyFunc func, gboolean expect_pdu,
+                               GAtExpectMsgLenFunc expect_msglen_func,
+                               gpointer user_data,
+                               GDestroyNotify destroy_notify)
+{
+       struct at_notify *notify;
+       struct at_notify_node *node;
+       struct at_chat *chat;
+       chat = child->parent;
+
+       if (chat == NULL || chat->notify_list == NULL)
+               return 0;
+
+       if (func == NULL)
+               return 0;
+
+       if (prefix == NULL || strlen(prefix) == 0)
+               return 0;
+
+       notify = g_hash_table_lookup(chat->notify_list, prefix);
+
+       if (!notify)
+               notify = at_notify_create(chat, prefix, expect_pdu, 
expect_msglen_func);
+
+       if (!notify || notify->pdu != expect_pdu)
+               return 0;
+
+       node = g_try_new0(struct at_notify_node, 1);
+       if (!node)
+               return 0;
+
+       node->id = chat->next_notify_id++;
+       node->callback = func;
+       node->user_data = user_data;
+       node->notify = destroy_notify;
+
+       notify->nodes = g_slist_prepend(notify->nodes, node);
+
+       return node->id;
+}
-- 
1.6.3.3

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

Reply via email to