---
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