All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 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 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 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 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 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.