* [PATCH 01/11] Rename g_at_server_send_result @ 2010-03-17 14:30 Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 02/11] Add framework of server parser Zhenhua Zhang 2010-03-17 14:38 ` [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang 0 siblings, 2 replies; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1337 bytes --] Rename it to g_at_server_send_final. --- gatchat/gatserver.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 7577de2..46fa423 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -148,7 +148,7 @@ static void send_common(GAtServer *server, const char *buf, unsigned int len) g_at_server_wakeup_writer(server); } -static void g_at_server_send_result(GAtServer *server, GAtServerResult result) +static void g_at_server_send_final(GAtServer *server, GAtServerResult result) { struct v250_settings v250 = server->v250; const char *result_str = server_result_to_string(result); @@ -353,7 +353,7 @@ static void new_bytes(GAtServer *p) * According to section 5.2.4 and 5.6 of V250, * Empty commands must be OK by the DCE */ - g_at_server_send_result(p, G_AT_SERVER_RESULT_OK); + g_at_server_send_final(p, G_AT_SERVER_RESULT_OK); ring_buffer_drain(p->read_buf, p->read_so_far); break; @@ -363,7 +363,7 @@ static void new_bytes(GAtServer *p) case PARSER_RESULT_REPEAT_LAST: /* TODO */ - g_at_server_send_result(p, G_AT_SERVER_RESULT_OK); + g_at_server_send_final(p, G_AT_SERVER_RESULT_OK); ring_buffer_drain(p->read_buf, p->read_so_far); break; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 02/11] Add framework of server parser 2010-03-17 14:30 [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 03/11] Add basic command parsing Zhenhua Zhang 2010-03-17 17:55 ` [PATCH 02/11] Add framework of server parser Denis Kenzior 2010-03-17 14:38 ` [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang 1 sibling, 2 replies; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2795 bytes --] a. The parser fetch and parse one command per loop. The prefix is the command prefix without parameter. For example, the prefix of "AT+CLIP=1" is "+CLIP". b. Search registered notification node in command_list. Invoke the callback if found. c. Termiate the execution if the result is an error. Otherwise, parse next command. --- gatchat/gatserver.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 46fa423..fb82ad4 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -173,8 +173,103 @@ static void g_at_server_send_final(GAtServer *server, GAtServerResult result) send_common(server, buf, MIN(len, sizeof(buf)-1)); } +static inline gboolean is_extended_command_prefix(const char c) +{ + switch (c) { + case '+': + case '*': + case '!': + case '%': + return TRUE; + default: + return FALSE; + } +} + +static gboolean is_basic_command_prefix(const char *buf) +{ + if (g_ascii_isalpha(buf[0])) + return TRUE; + + if (buf[0] == '&' && g_ascii_isalpha(buf[1])) + return TRUE; + + return FALSE; +} + +static GAtServerResult at_command_notify(GAtServer *server, char *command, + char *prefix) +{ + GAtServerResult res = G_AT_SERVER_RESULT_ERROR; + + return res; +} + +static char *parse_extended_command(GAtServer *server, const char *buf, + char *prefix) +{ + return NULL; +} + +static char *parse_basic_command(GAtServer *server, const char *buf, + char *prefix) +{ + return NULL; +} + +static char *parse_next_command(GAtServer *server, const char *buf, + char *prefix) +{ + char *command = NULL; + char c = *buf; + + /* fetch one command and get its prefix */ + if (is_extended_command_prefix(c)) + command = parse_extended_command(server, buf, prefix); + else if (is_basic_command_prefix(buf)) + command = parse_basic_command(server, buf, prefix); + + return command; +} + static void server_parse_line(GAtServer *server, char *line) { + GAtServerResult res = G_AT_SERVER_RESULT_ERROR; + char *buf = line; + char *command = NULL; + char prefix[20]; + + while (buf) { + char c = *buf; + + /* skip semicolon */ + if (c == ';') + c = *(++buf); + + if (c == '\0') { + res = G_AT_SERVER_RESULT_OK; + break; + } + + command = parse_next_command(server, buf, prefix); + if (!command) { + res = G_AT_SERVER_RESULT_ERROR; + break; + } + + res = at_command_notify(server, command, prefix); + if (res != G_AT_SERVER_RESULT_OK) { + g_free(command); + break; + } + + buf += strlen(command); + + g_free(command); + } + + g_at_server_send_final(server, res); + g_free(line); } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 03/11] Add basic command parsing 2010-03-17 14:30 ` [PATCH 02/11] Add framework of server parser Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 04/11] Add extended " Zhenhua Zhang 2010-03-17 18:02 ` [PATCH 03/11] Add basic command parsing Denis Kenzior 2010-03-17 17:55 ` [PATCH 02/11] Add framework of server parser Denis Kenzior 1 sibling, 2 replies; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2237 bytes --] According to V.250 5.3.1, the basic command is either a single character or the '&' followed by a single character. --- gatchat/gatserver.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 67 insertions(+), 1 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index fb82ad4..b68894d 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -211,10 +211,67 @@ static char *parse_extended_command(GAtServer *server, const char *buf, return NULL; } +static gboolean get_basic_prefix(const char *buf, char *prefix) +{ + char c = *buf; + + if (g_ascii_isalpha(c)) { + c = g_ascii_toupper(c); + if (c == 'S') { + int i = 0; + + prefix[0] = 'S'; + + /* V.250 5.3.2 'S' command follows with + * a parameter number. + */ + while (g_ascii_isdigit(buf[++i])) + prefix[i] = buf[i]; + + prefix[i] = '\0'; + } else { + prefix[0] = c; + prefix[1] = '\0'; + } + } else if (c == '&') { + prefix[0] = '&'; + prefix[1] = g_ascii_toupper(buf[1]); + prefix[2] = '\0'; + } else + return FALSE; + + return TRUE; +} + static char *parse_basic_command(GAtServer *server, const char *buf, char *prefix) { - return NULL; + char t = server->v250.s3; + int i; + + if (!get_basic_prefix(buf, prefix)) + return NULL; + + i = strlen(prefix); + + if (*buf == 'D' || *buf == 'd') { + /* All following characters are the part of the call */ + while (buf[i] && buf[i] != t) + i++; + } else { + /* Skip '=', '?' if have */ + if (buf[i] == '=') + i++; + + if (buf[i] == '?') + i++; + + /* V.250 5.3.1 The subparameter are all digits if have */ + while (g_ascii_isdigit(buf[i])) + i++; + } + + return g_strndup(buf, i); } static char *parse_next_command(GAtServer *server, const char *buf, @@ -263,6 +320,15 @@ static void server_parse_line(GAtServer *server, char *line) break; } + /* Commands like ATA, ATD, ATZ cause the remainder line + * to be ignored. + */ + if (!strcmp(prefix, "A") || !strcmp(prefix, "D") || + !strcmp(prefix, "Z")) { + g_free(command); + break; + } + buf += strlen(command); g_free(command); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 04/11] Add extended command parsing 2010-03-17 14:30 ` [PATCH 03/11] Add basic command parsing Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 05/11] Add server at command data structure Zhenhua Zhang 2010-03-17 18:02 ` [PATCH 03/11] Add basic command parsing Denis Kenzior 1 sibling, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1731 bytes --] --- gatchat/gatserver.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 56 insertions(+), 1 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index b68894d..f3807eb 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -197,6 +197,28 @@ static gboolean is_basic_command_prefix(const char *buf) return FALSE; } +static gboolean is_extended_character(const char c) +{ + if (g_ascii_isalpha(c)) + return TRUE; + + if (g_ascii_isdigit(c)) + return TRUE; + + switch (c) { + case '!': + case '%': + case '-': + case '.': + case '/': + case ':': + case '_': + return TRUE; + default: + return FALSE; + } +} + static GAtServerResult at_command_notify(GAtServer *server, char *command, char *prefix) { @@ -205,10 +227,43 @@ static GAtServerResult at_command_notify(GAtServer *server, char *command, return res; } +static gboolean get_extended_prefix(const char *buf, char *prefix) +{ + char c; + int i = 0; + + /* Skip '+' */ + prefix[0] = buf[0]; + + while ((c = buf[++i])) { + /* V.250 5.4.1 Extended command naming rules */ + if (!is_extended_character(c)) + break; + + prefix[i] = g_ascii_toupper(c); + } + + prefix[i] = '\0'; + + return TRUE; +} + static char *parse_extended_command(GAtServer *server, const char *buf, char *prefix) { - return NULL; + char *command; + char t = server->v250.s3; + char c = *buf; + int i = 0; + + while (c && c != t && c != ';') + c = buf[++i]; + + command = g_strndup(buf, i); + + get_extended_prefix(command, prefix); + + return command; } static gboolean get_basic_prefix(const char *buf, char *prefix) -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 05/11] Add server at command data structure 2010-03-17 14:30 ` [PATCH 04/11] Add extended " Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 06/11] Add notify at command callback Zhenhua Zhang 0 siblings, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 3614 bytes --] --- gatchat/gatserver.c | 27 +++++++++++++++++++++++++++ gatchat/gatserver.h | 22 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index f3807eb..bbaef52 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -88,6 +88,13 @@ struct v250_settings { unsigned int c108; /* set by &D<val> */ }; +/* AT command set that server supported */ +struct at_command { + GAtServerNotifyFunc notify; + gpointer user_data; + GDestroyNotify destroy_notify; +}; + struct _GAtServer { gint ref_count; /* Ref count */ struct v250_settings v250; /* V.250 command setting */ @@ -99,6 +106,7 @@ struct _GAtServer { gpointer user_disconnect_data; /* User disconnect data */ GAtDebugFunc debugf; /* Debugging output function */ gpointer debug_data; /* Data to pass to debug func */ + GHashTable *command_list; /* List of supported at command */ struct ring_buffer *read_buf; /* Current read buffer */ GQueue *write_queue; /* Write buffer queue */ guint max_read_attempts; /* Max reads per select */ @@ -733,6 +741,9 @@ static void g_at_server_cleanup(GAtServer *server) /* Cleanup pending data to write */ write_queue_free(server->write_queue); + g_hash_table_destroy(server->command_list); + server->command_list = NULL; + server->channel = NULL; } @@ -778,6 +789,16 @@ static void v250_settings_create(struct v250_settings *v250) v250->c108 = 0; } +static void at_notify_node_destroy(gpointer data) +{ + struct at_command *node = data; + + if (node->destroy_notify) + node->destroy_notify(node->user_data); + + g_free(node); +} + GAtServer *g_at_server_new(GIOChannel *io) { GAtServer *server; @@ -792,6 +813,9 @@ GAtServer *g_at_server_new(GIOChannel *io) server->ref_count = 1; v250_settings_create(&server->v250); server->channel = io; + server->command_list = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, + at_notify_node_destroy); server->read_buf = ring_buffer_new(BUF_SIZE); if (!server->read_buf) goto error; @@ -816,6 +840,9 @@ GAtServer *g_at_server_new(GIOChannel *io) return server; error: + if (server->command_list) + g_hash_table_destroy(server->command_list); + if (server->read_buf) ring_buffer_free(server->read_buf); diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h index 698f7e0..1c12a0d 100644 --- a/gatchat/gatserver.h +++ b/gatchat/gatserver.h @@ -26,6 +26,7 @@ extern "C" { #endif +#include "gatresult.h" #include "gatutil.h" struct _GAtServer; @@ -46,6 +47,27 @@ enum _GAtServerResult { typedef enum _GAtServerResult GAtServerResult; +/* Types of AT command: + * COMMAND_ONLY: command without any sub-parameters, e.g. ATA, AT+CLCC + * QUERY: command followed by '?', e.g. AT+CPIN? + * SUPPORT: command followed by '=?', e.g. AT+CSMS=? + * SET: command followed by '=', e.g. AT+CLIP=1 + * or, basic command followed with sub-parameters, e.g. ATD12345; + */ +enum _GAtServerRequestType { + G_AT_SERVER_REQUEST_TYPE_ERROR, + G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY, + G_AT_SERVER_REQUEST_TYPE_QUERY, + G_AT_SERVER_REQUEST_TYPE_SUPPORT, + G_AT_SERVER_REQUEST_TYPE_SET, +}; + +typedef enum _GAtServerRequestType GAtServerRequestType; + +typedef GAtServerResult (*GAtServerNotifyFunc)(GAtServerRequestType type, + GAtResult *result, + gpointer user_data); + GAtServer *g_at_server_new(GIOChannel *io); GAtServer *g_at_server_ref(GAtServer *server); -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 06/11] Add notify at command callback 2010-03-17 14:30 ` [PATCH 05/11] Add server at command data structure Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 07/11] Add g_at_server_register and unregister callback Zhenhua Zhang 2010-03-17 18:23 ` [PATCH 06/11] Add notify at command callback Denis Kenzior 0 siblings, 2 replies; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1682 bytes --] --- gatchat/gatserver.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index bbaef52..6e3347c 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -227,10 +227,48 @@ static gboolean is_extended_character(const char c) } } +static GAtServerRequestType get_command_type(char *buf, char *prefix) +{ + GAtServerRequestType type = G_AT_SERVER_REQUEST_TYPE_ERROR; + + buf += strlen(prefix); + + if (buf[0] == '\0') + /* Action command could have no sub-parameters */ + type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY; + else if (buf[0] == '?') + type = G_AT_SERVER_REQUEST_TYPE_QUERY; + else if (buf[0] == '=' && buf[1] == '?') + type = G_AT_SERVER_REQUEST_TYPE_SUPPORT; + else if (buf[0] == '=') + type = G_AT_SERVER_REQUEST_TYPE_SET; + else if (is_basic_command_prefix(prefix)) + /* Basic command could follow digits value, like ATE1 */ + type = G_AT_SERVER_REQUEST_TYPE_SET; + + return type; +} + static GAtServerResult at_command_notify(GAtServer *server, char *command, char *prefix) { GAtServerResult res = G_AT_SERVER_RESULT_ERROR; + struct at_command *node; + + node = g_hash_table_lookup(server->command_list, prefix); + if (node && node->notify) { + GAtServerRequestType type; + GAtResult result; + + type = get_command_type(command, prefix); + if (type == G_AT_SERVER_REQUEST_TYPE_ERROR) + return res; + + result.lines = g_slist_prepend(NULL, command); + result.final_or_pdu = 0; + + res = node->notify(type, &result, node->user_data); + } return res; } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 07/11] Add g_at_server_register and unregister callback 2010-03-17 14:30 ` [PATCH 06/11] Add notify at command callback Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 08/11] Add G_AT_SERVER_RESULT_EXT_ERROR Zhenhua Zhang 2010-03-17 18:23 ` [PATCH 06/11] Add notify at command callback Denis Kenzior 1 sibling, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2077 bytes --] --- gatchat/gatserver.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ gatchat/gatserver.h | 6 ++++++ 2 files changed, 54 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 6e3347c..c17a7b5 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -970,3 +970,51 @@ gboolean g_at_server_set_debug(GAtServer *server, GAtDebugFunc func, return TRUE; } + +gboolean g_at_server_register(GAtServer *server, char *prefix, + GAtServerNotifyFunc notify, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + struct at_command *node; + + if (server == NULL || server->command_list == NULL) + return FALSE; + + if (notify == NULL) + return FALSE; + + if (prefix == NULL || strlen(prefix) == 0) + return FALSE; + + node = g_try_new0(struct at_command, 1); + if (!node) + return FALSE; + + node->notify = notify; + node->user_data = user_data; + node->destroy_notify = destroy_notify; + + g_hash_table_replace(server->command_list, g_strdup(prefix), node); + + return TRUE; +} + +gboolean g_at_server_unregister(GAtServer *server, const char *prefix) +{ + struct at_command *node; + + if (server == NULL || server->command_list == NULL) + return FALSE; + + if (prefix == NULL || strlen(prefix) == 0) + return FALSE; + + node = g_hash_table_lookup(server->command_list, prefix); + if (!node) + return FALSE; + + g_hash_table_remove(server->command_list, prefix); + + return TRUE; +} diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h index 1c12a0d..5e9eb62 100644 --- a/gatchat/gatserver.h +++ b/gatchat/gatserver.h @@ -81,6 +81,12 @@ gboolean g_at_server_set_debug(GAtServer *server, GAtDebugFunc func, gpointer user); +gboolean g_at_server_register(GAtServer *server, char *prefix, + GAtServerNotifyFunc notify, + gpointer user_data, + GDestroyNotify destroy_notify); +gboolean g_at_server_unregister(GAtServer *server, const char *prefix); + #ifdef __cplusplus } #endif -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 08/11] Add G_AT_SERVER_RESULT_EXT_ERROR 2010-03-17 14:30 ` [PATCH 07/11] Add g_at_server_register and unregister callback Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 09/11] Fix do not emit error if extended error has emitted Zhenhua Zhang 0 siblings, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 493 bytes --] --- gatchat/gatserver.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h index 5e9eb62..6fb78bd 100644 --- a/gatchat/gatserver.h +++ b/gatchat/gatserver.h @@ -43,6 +43,7 @@ enum _GAtServerResult { G_AT_SERVER_RESULT_NO_DIALTONE = 6, G_AT_SERVER_RESULT_BUSY = 7, G_AT_SERVER_RESULT_NO_ANSWER = 8, + G_AT_SERVER_RESULT_EXT_ERROR = 256, }; typedef enum _GAtServerResult GAtServerResult; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 09/11] Fix do not emit error if extended error has emitted 2010-03-17 14:30 ` [PATCH 08/11] Add G_AT_SERVER_RESULT_EXT_ERROR Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 10/11] Refactor g_at_server_send_final Zhenhua Zhang 0 siblings, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 560 bytes --] --- gatchat/gatserver.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index c17a7b5..b0138d6 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -165,6 +165,10 @@ static void g_at_server_send_final(GAtServer *server, GAtServerResult result) char r = v250.s4; unsigned int len; + /* Do not emit error if extended error has already been emitted */ + if (result == G_AT_SERVER_RESULT_EXT_ERROR) + return; + if (v250.quiet) return; -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 10/11] Refactor g_at_server_send_final 2010-03-17 14:30 ` [PATCH 09/11] Fix do not emit error if extended error has emitted Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 11/11] Add utilities to send server response Zhenhua Zhang 0 siblings, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2266 bytes --] --- gatchat/gatserver.c | 43 +++++++++++++++++++++++++++---------------- 1 files changed, 27 insertions(+), 16 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index b0138d6..7ac6d34 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -33,6 +33,8 @@ #include "gatserver.h" #define BUF_SIZE 4096 +/* <cr><lf> + the max length of information text + <cr><lf> */ +#define MAX_TEXT_SIZE 2048+4 /* #define WRITE_SCHEDULER_DEBUG 1 */ enum ParserState { @@ -156,35 +158,44 @@ static void send_common(GAtServer *server, const char *buf, unsigned int len) g_at_server_wakeup_writer(server); } -static void g_at_server_send_final(GAtServer *server, GAtServerResult result) +static void send_result_common(GAtServer *server, const char *result) { - struct v250_settings v250 = server->v250; - const char *result_str = server_result_to_string(result); - char buf[1024]; - char t = v250.s3; - char r = v250.s4; + char buf[MAX_TEXT_SIZE]; + char t = server->v250.s3; + char r = server->v250.s4; unsigned int len; - /* Do not emit error if extended error has already been emitted */ - if (result == G_AT_SERVER_RESULT_EXT_ERROR) - return; - - if (v250.quiet) + if (server->v250.quiet) return; - if (result_str == NULL) + if (result == NULL) return; - if (v250.is_v1) - len = snprintf(buf, sizeof(buf), "%c%c%s%c%c", t, r, result_str, + if (server->v250.is_v1) + len = snprintf(buf, sizeof(buf), "%c%c%s%c%c", t, r, result, t, r); else - len = snprintf(buf, sizeof(buf), "%u%c", (unsigned int) result, - t); + len = snprintf(buf, sizeof(buf), "%s%c", result, t); send_common(server, buf, MIN(len, sizeof(buf)-1)); } +static void g_at_server_send_final(GAtServer *server, GAtServerResult result) +{ + char buf[1024]; + + /* Do not emit error if extended error has already been emitted */ + if (result == G_AT_SERVER_RESULT_EXT_ERROR) + return; + + if (server->v250.is_v1) + sprintf(buf, "%s", server_result_to_string(result)); + else + sprintf(buf, "%u", (unsigned int)result); + + send_result_common(server, buf); +} + static inline gboolean is_extended_command_prefix(const char c) { switch (c) { -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 11/11] Add utilities to send server response 2010-03-17 14:30 ` [PATCH 10/11] Refactor g_at_server_send_final Zhenhua Zhang @ 2010-03-17 14:30 ` Zhenhua Zhang 0 siblings, 0 replies; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2417 bytes --] The server response could be either result code or information text. Result code types: final, intermediate and unsolicited. Information text: one or multiple lines of text. --- gatchat/gatserver.c | 37 +++++++++++++++++++++++++++++++++++++ gatchat/gatserver.h | 11 +++++++++++ 2 files changed, 48 insertions(+), 0 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 7ac6d34..06ea912 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -196,6 +196,43 @@ static void g_at_server_send_final(GAtServer *server, GAtServerResult result) send_result_common(server, buf); } +void g_at_server_send_intermediate(GAtServer *server, const char *result) +{ + send_result_common(server, result); +} + +void g_at_server_send_unsolicited(GAtServer *server, const char *result) +{ + send_result_common(server, result); +} + +void g_at_server_send_info_text(GAtServer *server, GSList *text) +{ + char buf[MAX_TEXT_SIZE]; + char t = server->v250.s3; + char r = server->v250.s4; + unsigned int len; + GSList *l = text; + char *line; + + if (!text) + return; + + while(l) { + line = l->data; + if (!line) + return; + + len = snprintf(buf, sizeof(buf), "%c%c%s", t, r, line); + send_common(server, buf, MIN(len, sizeof(buf)-1)); + + l = l->next; + } + + len = snprintf(buf, sizeof(buf), "%c%c", t, r); + send_common(server, buf, len); +} + static inline gboolean is_extended_command_prefix(const char c) { switch (c) { diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h index 6fb78bd..19d7cb5 100644 --- a/gatchat/gatserver.h +++ b/gatchat/gatserver.h @@ -88,6 +88,17 @@ gboolean g_at_server_register(GAtServer *server, char *prefix, GDestroyNotify destroy_notify); gboolean g_at_server_unregister(GAtServer *server, const char *prefix); +/* Send an intermediate result code to report the progress. E.g. CONNECT */ +void g_at_server_send_intermediate(GAtServer *server, const char *result); + +/* Send an unsolicited result code. E.g. RING */ +void g_at_server_send_unsolicited(GAtServer *server, const char *result); + +/* Send an information text. The text could contain multiple lines. Each + * line, including line terminators, should not exceed 2048 characters. + */ +void g_at_server_send_info_text(GAtServer *server, GSList *text); + #ifdef __cplusplus } #endif -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 06/11] Add notify at command callback 2010-03-17 14:30 ` [PATCH 06/11] Add notify at command callback Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 07/11] Add g_at_server_register and unregister callback Zhenhua Zhang @ 2010-03-17 18:23 ` Denis Kenzior 1 sibling, 0 replies; 16+ messages in thread From: Denis Kenzior @ 2010-03-17 18:23 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1200 bytes --] Hi Zhenhua, > --- > gatchat/gatserver.c | 38 ++++++++++++++++++++++++++++++++++++++ > 1 files changed, 38 insertions(+), 0 deletions(-) > > diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c > index bbaef52..6e3347c 100644 > --- a/gatchat/gatserver.c > +++ b/gatchat/gatserver.c > @@ -227,10 +227,48 @@ static gboolean is_extended_character(const char c) > } > } > > static GAtServerResult at_command_notify(GAtServer *server, char *command, > char *prefix) > { > GAtServerResult res = G_AT_SERVER_RESULT_ERROR; > + struct at_command *node; > + > + node = g_hash_table_lookup(server->command_list, prefix); > + if (node && node->notify) { > + GAtServerRequestType type; > + GAtResult result; > + > + type = get_command_type(command, prefix); > + if (type == G_AT_SERVER_REQUEST_TYPE_ERROR) > + return res; > + > + result.lines = g_slist_prepend(NULL, command); > + result.final_or_pdu = 0; > + > + res = node->notify(type, &result, node->user_data); > + } Are you freeing the slist anywhere? In general you might want to run valgrind before submitting patches just to make sure there are no visible leaks. Regards, -Denis ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 03/11] Add basic command parsing 2010-03-17 14:30 ` [PATCH 03/11] Add basic command parsing Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 04/11] Add extended " Zhenhua Zhang @ 2010-03-17 18:02 ` Denis Kenzior 1 sibling, 0 replies; 16+ messages in thread From: Denis Kenzior @ 2010-03-17 18:02 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1847 bytes --] Hi Zhenhua, > According to V.250 5.3.1, the basic command is either a single > character or the '&' followed by a single character. > --- > gatchat/gatserver.c | 68 > ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 67 > insertions(+), 1 deletions(-) > > diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c > index fb82ad4..b68894d 100644 > --- a/gatchat/gatserver.c > +++ b/gatchat/gatserver.c > @@ -211,10 +211,67 @@ static char *parse_extended_command(GAtServer > *server, const char *buf, return NULL; > } > > +static gboolean get_basic_prefix(const char *buf, char *prefix) > +{ > + char c = *buf; > + > + if (g_ascii_isalpha(c)) { if (!g_ascii_isalpha && c != '&') return No nested ifs if you can avoid them please. > + c = g_ascii_toupper(c); > + if (c == 'S') { > + int i = 0; > + > + prefix[0] = 'S'; > + > + /* V.250 5.3.2 'S' command follows with > + * a parameter number. > + */ > + while (g_ascii_isdigit(buf[++i])) > + prefix[i] = buf[i]; > + > + prefix[i] = '\0'; > + } else { > + prefix[0] = c; > + prefix[1] = '\0'; > + } > + } else if (c == '&') { > + prefix[0] = '&'; > + prefix[1] = g_ascii_toupper(buf[1]); > + prefix[2] = '\0'; > + } else > + return FALSE; > + > + return TRUE; > +} > + > static char *parse_next_command(GAtServer *server, const char *buf, > @@ -263,6 +320,15 @@ static void server_parse_line(GAtServer *server, char > *line) break; > } > > + /* Commands like ATA, ATD, ATZ cause the remainder line > + * to be ignored. > + */ > + if (!strcmp(prefix, "A") || !strcmp(prefix, "D") || > + !strcmp(prefix, "Z")) { > + g_free(command); > + break; > + } > + strcmp might be overkill here > buf += strlen(command); > > g_free(command); > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 02/11] Add framework of server parser 2010-03-17 14:30 ` [PATCH 02/11] Add framework of server parser Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 03/11] Add basic command parsing Zhenhua Zhang @ 2010-03-17 17:55 ` Denis Kenzior 1 sibling, 0 replies; 16+ messages in thread From: Denis Kenzior @ 2010-03-17 17:55 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2727 bytes --] Hi Zhenhua, > a. The parser fetch and parse one command per loop. The prefix is > the command prefix without parameter. For example, the prefix of > "AT+CLIP=1" is "+CLIP". > > b. Search registered notification node in command_list. Invoke the > callback if found. > > c. Termiate the execution if the result is an error. Otherwise, > parse next command. > --- > gatchat/gatserver.c | 95 > +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 > insertions(+), 0 deletions(-) > > diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c > index 46fa423..fb82ad4 100644 > --- a/gatchat/gatserver.c > +++ b/gatchat/gatserver.c > @@ -173,8 +173,103 @@ static void g_at_server_send_final(GAtServer *server, > GAtServerResult result) send_common(server, buf, MIN(len, sizeof(buf)-1)); > } > > +static inline gboolean is_extended_command_prefix(const char c) > +{ > + switch (c) { > + case '+': > + case '*': > + case '!': > + case '%': > + return TRUE; > + default: > + return FALSE; > + } > +} So I don't see the point of a patch that removes the entire function, then puts the same function back in with the same name. If you want to rename it, send a patch to do so. > static void server_parse_line(GAtServer *server, char *line) > { > + GAtServerResult res = G_AT_SERVER_RESULT_ERROR; > + char *buf = line; > + char *command = NULL; > + char prefix[20]; > + > + while (buf) { So this part is wrong, buf will never be NULL. I suggest you preserve the logic of the current implementation here. > + char c = *buf; > + > + /* skip semicolon */ > + if (c == ';') > + c = *(++buf); > + > + if (c == '\0') { > + res = G_AT_SERVER_RESULT_OK; > + break; > + } > + > + command = parse_next_command(server, buf, prefix); > + if (!command) { > + res = G_AT_SERVER_RESULT_ERROR; > + break; > + } Why is a char * being allocated by parse_next_command? What is the purpose? I suggest you get rid of this and perform notifications there. It is too hard to keep track of who should free what and where otherwise. > + > + res = at_command_notify(server, command, prefix); I've mentioned this before, I don't like returning a result here. We should simply store the last result given to g_at_server_send_final or g_at_server_send_ext_final (e.g. do not send it out right away). If it is not OK then quit command processing and send the final result. > + if (res != G_AT_SERVER_RESULT_OK) { > + g_free(command); > + break; > + } > + > + buf += strlen(command); > + > + g_free(command); > + } > + > + g_at_server_send_final(server, res); > + > g_free(line); > } > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 01/11] Rename g_at_server_send_result 2010-03-17 14:30 [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 02/11] Add framework of server parser Zhenhua Zhang @ 2010-03-17 14:38 ` Zhenhua Zhang 2010-03-17 18:24 ` Denis Kenzior 1 sibling, 1 reply; 16+ messages in thread From: Zhenhua Zhang @ 2010-03-17 14:38 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 346 bytes --] Hi On 03/17/2010 10:30 PM, Zhang, Zhenhua wrote: > Rename it to g_at_server_send_final. > --- > gatchat/gatserver.c | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) > Sorry, I forgot the first patch. Please review the first patch as attached. Otherwise, these patches could not be applied. Thanks. Zhenhua [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Remove-old-server_parse_line.patch --] [-- Type: text/x-patch, Size: 1748 bytes --] >From 588126076e1fc10f57b75afe734d51046ab46d6d Mon Sep 17 00:00:00 2001 From: Zhenhua Zhang <zhenhua.zhang@intel.com> Date: Wed, 17 Mar 2010 16:36:22 +0800 Subject: [PATCH] Remove old server_parse_line --- gatchat/gatserver.c | 49 ------------------------------------------------- 1 files changed, 0 insertions(+), 49 deletions(-) diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c index 079451f..7577de2 100644 --- a/gatchat/gatserver.c +++ b/gatchat/gatserver.c @@ -173,57 +173,8 @@ static void g_at_server_send_result(GAtServer *server, GAtServerResult result) send_common(server, buf, MIN(len, sizeof(buf)-1)); } -static inline gboolean is_at_command_prefix(const char c) -{ - switch (c) { - case '+': - case '*': - case '!': - case '%': - return TRUE; - default: - return FALSE; - } -} - -static void parse_at_command(GAtServer *server, char *buf) -{ - g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR); -} - -static void parse_v250_settings(GAtServer *server, char *buf) -{ - g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR); -} - static void server_parse_line(GAtServer *server, char *line) { - gsize i = 0; - char c; - - if (line == NULL) { - g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR); - goto done; - } - - if (line[0] == '\0') { - g_at_server_send_result(server, G_AT_SERVER_RESULT_OK); - goto done; - } - - c = line[i]; - /* skip semicolon */ - if (c == ';') - c = line[++i]; - - if (is_at_command_prefix(c) || c == 'A' || c == 'D' || c == 'H') - parse_at_command(server, line + i); - else if (g_ascii_isalpha(c) || c == '&') - parse_v250_settings(server, line + i); - else - g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR); - -done: g_free(line); } -- 1.6.6.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 01/11] Rename g_at_server_send_result 2010-03-17 14:38 ` [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang @ 2010-03-17 18:24 ` Denis Kenzior 0 siblings, 0 replies; 16+ messages in thread From: Denis Kenzior @ 2010-03-17 18:24 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 348 bytes --] Hi Zhenhua, > Sorry, I forgot the first patch. Please review the first patch as > attached. Otherwise, these patches could not be applied. Please get rid of this patch and rebase the rest appropriately. I mentioned in the other reply, there's no sense to remove a bunch of code only to add nearly the same back in. Regards, -Denis ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2010-03-17 18:24 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-03-17 14:30 [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 02/11] Add framework of server parser Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 03/11] Add basic command parsing Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 04/11] Add extended " Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 05/11] Add server at command data structure Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 06/11] Add notify at command callback Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 07/11] Add g_at_server_register and unregister callback Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 08/11] Add G_AT_SERVER_RESULT_EXT_ERROR Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 09/11] Fix do not emit error if extended error has emitted Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 10/11] Refactor g_at_server_send_final Zhenhua Zhang 2010-03-17 14:30 ` [PATCH 11/11] Add utilities to send server response Zhenhua Zhang 2010-03-17 18:23 ` [PATCH 06/11] Add notify at command callback Denis Kenzior 2010-03-17 18:02 ` [PATCH 03/11] Add basic command parsing Denis Kenzior 2010-03-17 17:55 ` [PATCH 02/11] Add framework of server parser Denis Kenzior 2010-03-17 14:38 ` [PATCH 01/11] Rename g_at_server_send_result Zhenhua Zhang 2010-03-17 18:24 ` Denis Kenzior
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.