All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Updated patches to handle the asynchronized callback
@ 2010-03-29 13:50 Zhenhua Zhang
  2010-03-29 13:50 ` [PATCH 1/3] Refactor the command parsing Zhenhua Zhang
  0 siblings, 1 reply; 6+ messages in thread
From: Zhenhua Zhang @ 2010-03-29 13:50 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 328 bytes --]

Hi,

I updated the patches according to the comments and did following changes:

1. removed last_result since it seems no use at all.
2. rename g_at_server_send_flush to g_at_server_send_result. It makes code easier to read.
3. add parse_ready flag to parse one command line at one time.

Please review them. Thanks!


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] Refactor the command parsing
  2010-03-29 13:50 [PATCH 0/3] Updated patches to handle the asynchronized callback Zhenhua Zhang
@ 2010-03-29 13:50 ` Zhenhua Zhang
  2010-03-29 13:50   ` [PATCH 2/3] Add server send result code Zhenhua Zhang
  2010-03-29 19:35   ` [PATCH 1/3] Refactor the command parsing Denis Kenzior
  0 siblings, 2 replies; 6+ messages in thread
From: Zhenhua Zhang @ 2010-03-29 13:50 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 6204 bytes --]

---
 gatchat/gatserver.c |  103 +++++++++++++++++++++++++++-----------------------
 1 files changed, 56 insertions(+), 47 deletions(-)

diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
index c75fbf5..07999a8 100644
--- a/gatchat/gatserver.c
+++ b/gatchat/gatserver.c
@@ -112,6 +112,8 @@ struct _GAtServer {
 	guint max_read_attempts;		/* Max reads per select */
 	enum ParserState parser_state;
 	gboolean destroyed;			/* Re-entrancy guard */
+	char *read_line;			/* Current read line */
+	unsigned int read_pos;			/* Current read offset */
 };
 
 static void g_at_server_wakeup_writer(GAtServer *server);
@@ -215,7 +217,7 @@ static void at_command_notify(GAtServer *server, char *command,
 	g_slist_free(result.lines);
 }
 
-static unsigned int parse_extended_command(GAtServer *server, char *buf)
+static void parse_extended_command(GAtServer *server, char *buf)
 {
 	const char *valid_extended_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 						"0123456789!%-./:_";
@@ -230,7 +232,7 @@ static unsigned int parse_extended_command(GAtServer *server, char *buf)
 	prefix_len = strcspn(buf, separators);
 
 	if (prefix_len > 17 || prefix_len < 2)
-		return 0;
+		goto error;
 
 	/* Convert to upper case, we will always use upper case naming */
 	for (i = 0; i < prefix_len; i++)
@@ -239,17 +241,17 @@ static unsigned int parse_extended_command(GAtServer *server, char *buf)
 	prefix[prefix_len] = '\0';
 
 	if (strspn(prefix + 1, valid_extended_chars) != (prefix_len - 1))
-		return 0;
+		goto error;
 
 	/*
 	 * V.250 Section 5.4.1: "The first character following "+" shall be
 	 * an alphabetic character in the range "A" through "Z".
 	 */
 	if (prefix[1] <= 'A' || prefix[1] >= 'Z')
-		return 0;
+		goto error;
 
 	if (buf[i] != '\0' && buf[i] != ';' && buf[i] != '?' && buf[i] != '=')
-		return 0;
+		goto error;
 
 	type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
 
@@ -265,16 +267,16 @@ static unsigned int parse_extended_command(GAtServer *server, char *buf)
 
 		if (buf[i] == '?') {
 			if (seen_question || seen_equals)
-				return 0;
+				goto error;
 
 			if (buf[i + 1] != '\0' && buf[i + 1] != ';')
-				return 0;
+				goto error;
 
 			seen_question = TRUE;
 			type = G_AT_SERVER_REQUEST_TYPE_QUERY;
 		} else if (buf[i] == '=') {
 			if (seen_equals || seen_question)
-				return 0;
+				goto error;
 
 			seen_equals = TRUE;
 
@@ -291,10 +293,15 @@ next:
 	/* We can scratch in this buffer, so mark ';' as null */
 	buf[i] = '\0';
 
+	/* Also consume the terminating null */
+	server->read_pos += i + 1;
+
 	at_command_notify(server, buf, prefix, type);
 
-	/* Also consume the terminating null */
-	return i + 1;
+	return;
+
+error:
+	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
 }
 
 static int get_basic_prefix_size(const char *buf)
@@ -336,16 +343,20 @@ static int get_basic_prefix_size(const char *buf)
 	return 0;
 }
 
-static unsigned int parse_basic_command(GAtServer *server, char *buf)
+static void parse_basic_command(GAtServer *server, char *buf)
 {
 	gboolean seen_equals = FALSE;
 	char prefix[4], tmp;
-	unsigned int i, prefix_size;
+	unsigned int i, prefix_size, end;
 	GAtServerRequestType type;
 
 	prefix_size = get_basic_prefix_size(buf);
 	if (prefix_size == 0)
-		return 0;
+		goto error;
+
+	/* Handle S-parameter with 100+ */
+	if (prefix_size > 3)
+		goto error;
 
 	i = prefix_size;
 	prefix[0] = g_ascii_toupper(buf[0]);
@@ -390,33 +401,39 @@ static unsigned int parse_basic_command(GAtServer *server, char *buf)
 	}
 
 done:
-	if (prefix_size <= 3) {
-		memcpy(prefix + 1, buf + 1, prefix_size - 1);
-		prefix[prefix_size] = '\0';
-
-		tmp = buf[i];
-		buf[i] = '\0';
-		at_command_notify(server, buf, prefix, type);
-		buf[i] = tmp;
-	} else /* Handle S-parameter with 100+ */
-		g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+	end = i;
 
 	/* Commands like ATA, ATZ cause the remainder line
 	 * to be ignored.
 	 */
 	if (prefix[0] == 'A' || prefix[0] == 'Z')
-		return strlen(buf);
+		i = strlen(buf);
 
 	/* Consume the seperator ';' */
 	if (buf[i] == ';')
 		i += 1;
 
-	return i;
+	/* Update read offset before notify the callback */
+	server->read_pos += i;
+
+	memcpy(prefix + 1, buf + 1, prefix_size - 1);
+	prefix[prefix_size] = '\0';
+
+	tmp = buf[end];
+	buf[end] = '\0';
+	at_command_notify(server, buf, prefix, type);
+	buf[end] = tmp;
+
+	return;
+
+error:
+	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
 }
 
-static void server_parse_line(GAtServer *server, char *line)
+static void server_parse_line(GAtServer *server)
 {
-	unsigned int pos = 0;
+	char *line = server->read_line;
+	unsigned int pos = server->read_pos;
 	unsigned int len = strlen(line);
 
 	if (len == 0) {
@@ -424,22 +441,10 @@ static void server_parse_line(GAtServer *server, char *line)
 		return;
 	}
 
-	while (pos < len) {
-		unsigned int consumed;
-
-		if (is_extended_command_prefix(line[pos]))
-			consumed = parse_extended_command(server, line + pos);
-		else
-			consumed = parse_basic_command(server, line + pos);
-
-		if (consumed == 0) {
-			g_at_server_send_final(server,
-						G_AT_SERVER_RESULT_ERROR);
-			break;
-		}
-
-		pos += consumed;
-	}
+	if (is_extended_command_prefix(line[pos]))
+		parse_extended_command(server, line + pos);
+	else
+		parse_basic_command(server, line + pos);
 }
 
 static enum ParserResult server_feed(GAtServer *server,
@@ -621,11 +626,13 @@ static void new_bytes(GAtServer *p)
 
 		case PARSER_RESULT_COMMAND:
 		{
-			char *line = extract_line(p);
+			g_free(p->read_line);
 
-			if (line) {
-				server_parse_line(p, line);
-				g_free(line);
+			p->read_line = extract_line(p);
+			if (p->read_line) {
+				p->read_pos = 0;
+
+				server_parse_line(p);
 			} else
 				g_at_server_send_final(p,
 						G_AT_SERVER_RESULT_ERROR);
@@ -795,6 +802,8 @@ static void g_at_server_cleanup(GAtServer *server)
 	g_hash_table_destroy(server->command_list);
 	server->command_list = NULL;
 
+	g_free(server->read_line);
+
 	server->channel = NULL;
 }
 
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] Add server send result code
  2010-03-29 13:50 ` [PATCH 1/3] Refactor the command parsing Zhenhua Zhang
@ 2010-03-29 13:50   ` Zhenhua Zhang
  2010-03-29 13:50     ` [PATCH 3/3] Add flag to parse one command line at once Zhenhua Zhang
  2010-03-29 20:13     ` [PATCH 2/3] Add server send result code Denis Kenzior
  2010-03-29 19:35   ` [PATCH 1/3] Refactor the command parsing Denis Kenzior
  1 sibling, 2 replies; 6+ messages in thread
From: Zhenhua Zhang @ 2010-03-29 13:50 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 6690 bytes --]

---
 gatchat/gatserver.c |   98 ++++++++++++++++++++++++++++++++++++++++++++-------
 gatchat/gatserver.h |   17 +++++++++
 2 files changed, 102 insertions(+), 13 deletions(-)

diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
index 07999a8..cad9d91 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 2052
 /* #define WRITE_SCHEDULER_DEBUG 1 */
 
 enum ParserState {
@@ -117,6 +119,7 @@ struct _GAtServer {
 };
 
 static void g_at_server_wakeup_writer(GAtServer *server);
+static void server_parse_line(GAtServer *server);
 
 static struct ring_buffer *allocate_next(GAtServer *server)
 {
@@ -158,11 +161,11 @@ 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 buf[MAX_TEXT_SIZE];
 	char t = v250.s3;
 	char r = v250.s4;
 	unsigned int len;
@@ -170,19 +173,88 @@ static void g_at_server_send_final(GAtServer *server, GAtServerResult result)
 	if (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,
+		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,
+		len = snprintf(buf, sizeof(buf), "%s%c", result,
 				t);
 
 	send_common(server, buf, MIN(len, sizeof(buf)-1));
 }
 
+static void g_at_server_send_result(GAtServer *server, GAtServerResult result)
+{
+	char buf[1024];
+
+	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);
+}
+
+void g_at_server_send_final(GAtServer *server, GAtServerResult result)
+{
+	char *line = server->read_line;
+	unsigned int pos = server->read_pos;
+	unsigned int len = strlen(line);
+
+	/* Continue only if the result is OK and we have further commands */
+	if (result == G_AT_SERVER_RESULT_OK && pos < len)
+		server_parse_line(server);
+	else if (result == G_AT_SERVER_RESULT_EXT_ERROR)
+		;	/* Skip */
+	else
+		g_at_server_send_result(server, result);
+}
+
+void g_at_server_send_ext_final(GAtServer *server, const char *result)
+{
+	send_result_common(server, result);
+}
+
+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) {
@@ -205,7 +277,7 @@ static void at_command_notify(GAtServer *server, char *command,
 	node = g_hash_table_lookup(server->command_list, prefix);
 
 	if (node == NULL) {
-		g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+		g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);
 		return;
 	}
 
@@ -301,7 +373,7 @@ next:
 	return;
 
 error:
-	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+	g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);
 }
 
 static int get_basic_prefix_size(const char *buf)
@@ -427,7 +499,7 @@ done:
 	return;
 
 error:
-	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+	g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);
 }
 
 static void server_parse_line(GAtServer *server)
@@ -437,7 +509,7 @@ static void server_parse_line(GAtServer *server)
 	unsigned int len = strlen(line);
 
 	if (len == 0) {
-		g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
+		g_at_server_send_result(server, G_AT_SERVER_RESULT_OK);
 		return;
 	}
 
@@ -620,7 +692,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_final(p, G_AT_SERVER_RESULT_OK);
+			g_at_server_send_result(p, G_AT_SERVER_RESULT_OK);
 			ring_buffer_drain(p->read_buf, p->read_so_far);
 			break;
 
@@ -634,14 +706,14 @@ static void new_bytes(GAtServer *p)
 
 				server_parse_line(p);
 			} else
-				g_at_server_send_final(p,
+				g_at_server_send_result(p,
 						G_AT_SERVER_RESULT_ERROR);
 			break;
 		}
 
 		case PARSER_RESULT_REPEAT_LAST:
 			/* TODO */
-			g_at_server_send_final(p, G_AT_SERVER_RESULT_OK);
+			g_at_server_send_result(p, G_AT_SERVER_RESULT_OK);
 			ring_buffer_drain(p->read_buf, p->read_so_far);
 			break;
 
diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h
index 2ae19ca..a508be6 100644
--- a/gatchat/gatserver.h
+++ b/gatchat/gatserver.h
@@ -87,6 +87,23 @@ gboolean g_at_server_register(GAtServer *server, char *prefix,
 					GDestroyNotify destroy_notify);
 gboolean g_at_server_unregister(GAtServer *server, const char *prefix);
 
+/* Send a final result code. E.g. G_AT_SERVER_RESULT_NO_DIALTONE */
+void g_at_server_send_final(GAtServer *server, GAtServerResult result);
+
+/* Send an extended final result code. E.g. +CME ERROR: SIM failure. */
+void g_at_server_send_ext_final(GAtServer *server, const char *result);
+
+/* 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] 6+ messages in thread

* [PATCH 3/3] Add flag to parse one command line at once
  2010-03-29 13:50   ` [PATCH 2/3] Add server send result code Zhenhua Zhang
@ 2010-03-29 13:50     ` Zhenhua Zhang
  2010-03-29 20:13     ` [PATCH 2/3] Add server send result code Denis Kenzior
  1 sibling, 0 replies; 6+ messages in thread
From: Zhenhua Zhang @ 2010-03-29 13:50 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2122 bytes --]

---
 gatchat/gatserver.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
index cad9d91..251c3b8 100644
--- a/gatchat/gatserver.c
+++ b/gatchat/gatserver.c
@@ -116,6 +116,7 @@ struct _GAtServer {
 	gboolean destroyed;			/* Re-entrancy guard */
 	char *read_line;			/* Current read line */
 	unsigned int read_pos;			/* Current read offset */
+	gboolean parse_ready;			/* Ready to parse command */
 };
 
 static void g_at_server_wakeup_writer(GAtServer *server);
@@ -196,6 +197,8 @@ static void g_at_server_send_result(GAtServer *server, GAtServerResult result)
 		sprintf(buf, "%u", (unsigned int)result);
 
 	send_result_common(server, buf);
+
+	server->parse_ready = TRUE;
 }
 
 void g_at_server_send_final(GAtServer *server, GAtServerResult result)
@@ -216,6 +219,8 @@ void g_at_server_send_final(GAtServer *server, GAtServerResult result)
 void g_at_server_send_ext_final(GAtServer *server, const char *result)
 {
 	send_result_common(server, result);
+
+	server->parse_ready = TRUE;
 }
 
 void g_at_server_send_intermediate(GAtServer *server, const char *result)
@@ -671,7 +676,7 @@ static void new_bytes(GAtServer *p)
 	unsigned char *buf = ring_buffer_read_ptr(p->read_buf, p->read_so_far);
 	enum ParserResult result;
 
-	while (p->channel && (p->read_so_far < len)) {
+	while (p->channel && p->parse_ready && (p->read_so_far < len)) {
 		gsize rbytes = MIN(len - p->read_so_far, wrap - p->read_so_far);
 		result = server_feed(p, (char *)buf, &rbytes);
 
@@ -703,6 +708,7 @@ static void new_bytes(GAtServer *p)
 			p->read_line = extract_line(p);
 			if (p->read_line) {
 				p->read_pos = 0;
+				p->parse_ready = FALSE;
 
 				server_parse_line(p);
 			} else
@@ -945,6 +951,7 @@ GAtServer *g_at_server_new(GIOChannel *io)
 	server->ref_count = 1;
 	v250_settings_create(&server->v250);
 	server->channel = io;
+	server->parse_ready = TRUE;
 	server->command_list = g_hash_table_new_full(g_str_hash, g_str_equal,
 							g_free,
 							at_notify_node_destroy);
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] Refactor the command parsing
  2010-03-29 13:50 ` [PATCH 1/3] Refactor the command parsing Zhenhua Zhang
  2010-03-29 13:50   ` [PATCH 2/3] Add server send result code Zhenhua Zhang
@ 2010-03-29 19:35   ` Denis Kenzior
  1 sibling, 0 replies; 6+ messages in thread
From: Denis Kenzior @ 2010-03-29 19:35 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 5072 bytes --]

Hi Zhenhua,

> ---
>  gatchat/gatserver.c |  103
>  +++++++++++++++++++++++++++----------------------- 1 files changed, 56
>  insertions(+), 47 deletions(-)
> 
> diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
> index c75fbf5..07999a8 100644
> --- a/gatchat/gatserver.c
> +++ b/gatchat/gatserver.c
> @@ -112,6 +112,8 @@ struct _GAtServer {
>  	guint max_read_attempts;		/* Max reads per select */
>  	enum ParserState parser_state;
>  	gboolean destroyed;			/* Re-entrancy guard */
> +	char *read_line;			/* Current read line */

How about char *last_cmd;

> +	unsigned int read_pos;			/* Current read offset */

And cur_pos;

>  };
> 
>  static void g_at_server_wakeup_writer(GAtServer *server);
> @@ -215,7 +217,7 @@ static void at_command_notify(GAtServer *server, char
>  *command, g_slist_free(result.lines);
>  }
> 
> -static unsigned int parse_extended_command(GAtServer *server, char *buf)
> +static void parse_extended_command(GAtServer *server, char *buf)
>  {
>  	const char *valid_extended_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>  						"0123456789!%-./:_";
> @@ -230,7 +232,7 @@ static unsigned int parse_extended_command(GAtServer
>  *server, char *buf) prefix_len = strcspn(buf, separators);
> 
>  	if (prefix_len > 17 || prefix_len < 2)
> -		return 0;
> +		goto error;
> 
>  	/* Convert to upper case, we will always use upper case naming */
>  	for (i = 0; i < prefix_len; i++)
> @@ -239,17 +241,17 @@ static unsigned int parse_extended_command(GAtServer
>  *server, char *buf) prefix[prefix_len] = '\0';
> 
>  	if (strspn(prefix + 1, valid_extended_chars) != (prefix_len - 1))
> -		return 0;
> +		goto error;
> 
>  	/*
>  	 * V.250 Section 5.4.1: "The first character following "+" shall be
>  	 * an alphabetic character in the range "A" through "Z".
>  	 */
>  	if (prefix[1] <= 'A' || prefix[1] >= 'Z')
> -		return 0;
> +		goto error;
> 
>  	if (buf[i] != '\0' && buf[i] != ';' && buf[i] != '?' && buf[i] != '=')
> -		return 0;
> +		goto error;
> 
>  	type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
> 
> @@ -265,16 +267,16 @@ static unsigned int parse_extended_command(GAtServer
>  *server, char *buf)
> 
>  		if (buf[i] == '?') {
>  			if (seen_question || seen_equals)
> -				return 0;
> +				goto error;
> 
>  			if (buf[i + 1] != '\0' && buf[i + 1] != ';')
> -				return 0;
> +				goto error;
> 
>  			seen_question = TRUE;
>  			type = G_AT_SERVER_REQUEST_TYPE_QUERY;
>  		} else if (buf[i] == '=') {
>  			if (seen_equals || seen_question)
> -				return 0;
> +				goto error;
> 
>  			seen_equals = TRUE;
> 
> @@ -291,10 +293,15 @@ next:
>  	/* We can scratch in this buffer, so mark ';' as null */
>  	buf[i] = '\0';
> 
> +	/* Also consume the terminating null */
> +	server->read_pos += i + 1;
> +
>  	at_command_notify(server, buf, prefix, type);
> 
> -	/* Also consume the terminating null */
> -	return i + 1;
> +	return;
> +
> +error:
> +	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
>  }

So I suggest you leave this function as is and do the read_pos logic in 
server_parse_line.

> 
>  static int get_basic_prefix_size(const char *buf)
> @@ -336,16 +343,20 @@ static int get_basic_prefix_size(const char *buf)
>  	return 0;
>  }
> 
> -static unsigned int parse_basic_command(GAtServer *server, char *buf)
> +static void parse_basic_command(GAtServer *server, char *buf)
>  {
>  	gboolean seen_equals = FALSE;
>  	char prefix[4], tmp;
> -	unsigned int i, prefix_size;
> +	unsigned int i, prefix_size, end;
>  	GAtServerRequestType type;
> 
>  	prefix_size = get_basic_prefix_size(buf);
>  	if (prefix_size == 0)
> -		return 0;
> +		goto error;
> +
> +	/* Handle S-parameter with 100+ */
> +	if (prefix_size > 3)
> +		goto error;
> 
>  	i = prefix_size;
>  	prefix[0] = g_ascii_toupper(buf[0]);
> @@ -390,33 +401,39 @@ static unsigned int parse_basic_command(GAtServer
>  *server, char *buf) }
> 
>  done:
> -	if (prefix_size <= 3) {
> -		memcpy(prefix + 1, buf + 1, prefix_size - 1);
> -		prefix[prefix_size] = '\0';
> -
> -		tmp = buf[i];
> -		buf[i] = '\0';
> -		at_command_notify(server, buf, prefix, type);
> -		buf[i] = tmp;
> -	} else /* Handle S-parameter with 100+ */
> -		g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
> +	end = i;
> 
>  	/* Commands like ATA, ATZ cause the remainder line
>  	 * to be ignored.
>  	 */
>  	if (prefix[0] == 'A' || prefix[0] == 'Z')
> -		return strlen(buf);
> +		i = strlen(buf);
> 
>  	/* Consume the seperator ';' */
>  	if (buf[i] == ';')
>  		i += 1;
> 
> -	return i;
> +	/* Update read offset before notify the callback */
> +	server->read_pos += i;
> +
> +	memcpy(prefix + 1, buf + 1, prefix_size - 1);
> +	prefix[prefix_size] = '\0';
> +
> +	tmp = buf[end];
> +	buf[end] = '\0';
> +	at_command_notify(server, buf, prefix, type);
> +	buf[end] = tmp;
> +
> +	return;
> +
> +error:
> +	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
>  }
> 

As above.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] Add server send result code
  2010-03-29 13:50   ` [PATCH 2/3] Add server send result code Zhenhua Zhang
  2010-03-29 13:50     ` [PATCH 3/3] Add flag to parse one command line at once Zhenhua Zhang
@ 2010-03-29 20:13     ` Denis Kenzior
  1 sibling, 0 replies; 6+ messages in thread
From: Denis Kenzior @ 2010-03-29 20:13 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 5638 bytes --]

Hi Zhenhua,

> +static void g_at_server_send_result(GAtServer *server, GAtServerResult
>  result) +{
> +	char buf[1024];
> +
> +	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);
> +}

Please get rid of this function, it serves no purpose and is utterly 
confusing.  If you would put the contents at the else clause of 
g_at_server_send_final then the same thing will be accomplished.

> +
> +void g_at_server_send_final(GAtServer *server, GAtServerResult result)
> +{
> +	char *line = server->read_line;
> +	unsigned int pos = server->read_pos;
> +	unsigned int len = strlen(line);
> +
> +	/* Continue only if the result is OK and we have further commands */
> +	if (result == G_AT_SERVER_RESULT_OK && pos < len)
> +		server_parse_line(server);
> +	else if (result == G_AT_SERVER_RESULT_EXT_ERROR)
> +		;	/* Skip */

Nobody should ever call this function with EXT_ERROR

> +	else
> +		g_at_server_send_result(server, result);
> +}
> +
> +void g_at_server_send_ext_final(GAtServer *server, const char *result)
> +{
> +	send_result_common(server, result);

Why don't we do the same server_parse_line magic here?

> +}
> +
> +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;
> +	}

Using a for loop is more compact here.

> +
> +	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) {
> @@ -205,7 +277,7 @@ static void at_command_notify(GAtServer *server, char
>  *command, node = g_hash_table_lookup(server->command_list, prefix);
> 
>  	if (node == NULL) {
> -		g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
> +		g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);

Leave it as is

>  		return;
>  	}
> 
> @@ -301,7 +373,7 @@ next:
>  	return;
> 
>  error:
> -	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
> +	g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);

Leave it as is

>  }
> 
>  static int get_basic_prefix_size(const char *buf)
> @@ -427,7 +499,7 @@ done:
>  	return;
> 
>  error:
> -	g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
> +	g_at_server_send_result(server, G_AT_SERVER_RESULT_ERROR);

And again,

>  }
> 
>  static void server_parse_line(GAtServer *server)
> @@ -437,7 +509,7 @@ static void server_parse_line(GAtServer *server)
>  	unsigned int len = strlen(line);
> 
>  	if (len == 0) {
> -		g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
> +		g_at_server_send_result(server, G_AT_SERVER_RESULT_OK);

And again

>  		return;
>  	}
> 
> @@ -620,7 +692,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_final(p, G_AT_SERVER_RESULT_OK);
> +			g_at_server_send_result(p, G_AT_SERVER_RESULT_OK);

And here

>  			ring_buffer_drain(p->read_buf, p->read_so_far);
>  			break;
> 
> @@ -634,14 +706,14 @@ static void new_bytes(GAtServer *p)
> 
>  				server_parse_line(p);
>  			} else
> -				g_at_server_send_final(p,
> +				g_at_server_send_result(p,
>  						G_AT_SERVER_RESULT_ERROR);

And here

>  			break;
>  		}
> 
>  		case PARSER_RESULT_REPEAT_LAST:
>  			/* TODO */
> -			g_at_server_send_final(p, G_AT_SERVER_RESULT_OK);
> +			g_at_server_send_result(p, G_AT_SERVER_RESULT_OK);

And again here

>  			ring_buffer_drain(p->read_buf, p->read_so_far);
>  			break;
> 
> diff --git a/gatchat/gatserver.h b/gatchat/gatserver.h
> index 2ae19ca..a508be6 100644
> --- a/gatchat/gatserver.h
> +++ b/gatchat/gatserver.h
> @@ -87,6 +87,23 @@ gboolean g_at_server_register(GAtServer *server, char
>  *prefix, GDestroyNotify destroy_notify);
>  gboolean g_at_server_unregister(GAtServer *server, const char *prefix);
> 
> +/* Send a final result code. E.g. G_AT_SERVER_RESULT_NO_DIALTONE */
> +void g_at_server_send_final(GAtServer *server, GAtServerResult result);
> +
> +/* Send an extended final result code. E.g. +CME ERROR: SIM failure. */
> +void g_at_server_send_ext_final(GAtServer *server, const char *result);
> +
> +/* 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
> 

Regards,
-Denis

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-03-29 20:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-29 13:50 [PATCH 0/3] Updated patches to handle the asynchronized callback Zhenhua Zhang
2010-03-29 13:50 ` [PATCH 1/3] Refactor the command parsing Zhenhua Zhang
2010-03-29 13:50   ` [PATCH 2/3] Add server send result code Zhenhua Zhang
2010-03-29 13:50     ` [PATCH 3/3] Add flag to parse one command line at once Zhenhua Zhang
2010-03-29 20:13     ` [PATCH 2/3] Add server send result code Denis Kenzior
2010-03-29 19:35   ` [PATCH 1/3] Refactor the command parsing 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.