Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality
@ 2014-03-01 20:00 Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 2/6] shared/hfp: Add implementiation of processing commands Marcin Kraglak
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

Add two functions: hfp_gw_register_prefix_handler() and
hfp_gw_unregister_prefix_handler(). It will allow user to register for
specific command. Current implementation just put/remove handler data
from queue.
---
 Makefile.tools   |  1 +
 src/shared/hfp.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/hfp.h | 18 +++++++++++
 3 files changed, 118 insertions(+)

diff --git a/Makefile.tools b/Makefile.tools
index 9f7ba9f..31e1093 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -63,6 +63,7 @@ emulator_hfp_SOURCES = emulator/hfp.c \
 				monitor/mainloop.h monitor/mainloop.c \
 				src/shared/io.h src/shared/io-mainloop.c \
 				src/shared/util.h src/shared/util.c \
+				src/shared/queue.h src/shared/queue.c \
 				src/shared/ringbuf.h src/shared/ringbuf.c \
 				src/shared/hfp.h src/shared/hfp.c
 
diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 854cf46..4bf993d 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -32,6 +32,7 @@
 
 #include "src/shared/util.h"
 #include "src/shared/ringbuf.h"
+#include "src/shared/queue.h"
 #include "src/shared/io.h"
 #include "src/shared/hfp.h"
 
@@ -42,6 +43,7 @@ struct hfp_gw {
 	struct io *io;
 	struct ringbuf *read_buf;
 	struct ringbuf *write_buf;
+	struct queue *cmd_handlers;
 	bool writer_active;
 	bool permissive_syntax;
 	bool result_pending;
@@ -60,6 +62,37 @@ struct hfp_gw {
 	bool destroyed;
 };
 
+struct cmd_handler {
+	char *prefix;
+	void *user_data;
+	hfp_destroy_func_t destroy;
+	hfp_result_func_t callback;
+};
+
+static void destroy_cmd_handler(void *data)
+{
+	struct cmd_handler *handler = data;
+
+	if (handler->destroy)
+		handler->destroy(handler->user_data);
+
+	free(handler);
+}
+
+static bool match_handler_prefix(const void *a, const void *b)
+{
+	const struct cmd_handler *handler = a;
+	const char *prefix = b;
+
+	if (strlen(handler->prefix) != strlen(prefix))
+		return false;
+
+	if (memcmp(handler->prefix, prefix, strlen(prefix)))
+		return false;
+
+	return true;
+}
+
 static void write_watch_destroy(void *user_data)
 {
 	struct hfp_gw *hfp = user_data;
@@ -196,8 +229,19 @@ struct hfp_gw *hfp_gw_new(int fd)
 		return NULL;
 	}
 
+	hfp->cmd_handlers = queue_new();
+	if (!hfp->cmd_handlers) {
+		io_destroy(hfp->io);
+		ringbuf_free(hfp->write_buf);
+		ringbuf_free(hfp->read_buf);
+		free(hfp);
+		return NULL;
+	}
+
 	if (!io_set_read_handler(hfp->io, can_read_data,
 					hfp, read_watch_destroy)) {
+		queue_destroy(hfp->cmd_handlers,
+						destroy_cmd_handler);
 		io_destroy(hfp->io);
 		ringbuf_free(hfp->write_buf);
 		ringbuf_free(hfp->read_buf);
@@ -250,6 +294,9 @@ void hfp_gw_unref(struct hfp_gw *hfp)
 	ringbuf_free(hfp->write_buf);
 	hfp->write_buf = NULL;
 
+	queue_destroy(hfp->cmd_handlers, destroy_cmd_handler);
+	hfp->cmd_handlers = NULL;
+
 	if (!hfp->in_disconnect) {
 		free(hfp);
 		return;
@@ -405,6 +452,58 @@ bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
 	return true;
 }
 
+bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
+						const char *prefix,
+						void *user_data,
+						hfp_destroy_func_t destroy)
+{
+	struct cmd_handler *handler;
+
+	handler = new0(struct cmd_handler, 1);
+	if (!handler)
+		return false;
+
+	handler->callback = callback;
+	handler->user_data = user_data;
+
+	handler->prefix = strdup(prefix);
+	if (!handler->prefix) {
+		free(handler);
+		return false;
+	}
+
+	if (queue_find(hfp->cmd_handlers, match_handler_prefix,
+							handler->prefix)) {
+		destroy_cmd_handler(handler);
+		return false;
+	}
+
+	handler->destroy = destroy;
+
+	return queue_push_tail(hfp->cmd_handlers, handler);
+}
+
+bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix)
+{
+	struct cmd_handler *handler;
+	char *lookup_prefix;
+
+	lookup_prefix = strdup(prefix);
+	if (!lookup_prefix)
+		return false;
+
+	handler = queue_remove_if(hfp->cmd_handlers, match_handler_prefix,
+								lookup_prefix);
+	free(lookup_prefix);
+
+	if (!handler)
+		return false;
+
+	destroy_cmd_handler(handler);
+
+	return true;
+}
+
 static void disconnect_watch_destroy(void *user_data)
 {
 	struct hfp_gw *hfp = user_data;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index b0bd934..0755a46 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -60,6 +60,18 @@ enum hfp_error {
 	HFP_ERROR_NETWORK_NOT_ALLOWED		= 32,
 };
 
+enum hfp_gw_cmd_type {
+	HFP_GW_CMD_TYPE_READ,
+	HFP_GW_CMD_TYPE_SET,
+	HFP_GW_CMD_TYPE_TEST,
+	HFP_GW_CMD_TYPE_COMMAND
+};
+
+struct hfp_gw_result;
+
+typedef void (*hfp_result_func_t)(struct hfp_gw_result *result,
+				enum hfp_gw_cmd_type type, void *user_data);
+
 typedef void (*hfp_destroy_func_t)(void *user_data);
 typedef void (*hfp_debug_func_t)(const char *str, void *user_data);
 
@@ -94,3 +106,9 @@ bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
 					hfp_destroy_func_t destroy);
 
 bool hfp_gw_disconnect(struct hfp_gw *hfp);
+
+bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
+						const char *prefix,
+						void *user_data,
+						hfp_destroy_func_t destroy);
+bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);
-- 
1.8.3.1


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

* [PATCHv4 2/6] shared/hfp: Add implementiation of processing commands
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
@ 2014-03-01 20:00 ` Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 3/6] shared/hfp: Add get_number implementation Marcin Kraglak
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

It will look for prefix handler for given cammand.
---
 src/shared/hfp.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 94 insertions(+), 4 deletions(-)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 4bf993d..945f36e 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "src/shared/util.h"
 #include "src/shared/ringbuf.h"
@@ -69,6 +70,11 @@ struct cmd_handler {
 	hfp_result_func_t callback;
 };
 
+struct hfp_gw_result {
+	const char *data;
+	int offset;
+};
+
 static void destroy_cmd_handler(void *data)
 {
 	struct cmd_handler *handler = data;
@@ -130,6 +136,88 @@ static void wakeup_writer(struct hfp_gw *hfp)
 	hfp->writer_active = true;
 }
 
+static void skip_whitespace(struct hfp_gw_result *result)
+{
+	while (result->data[result->offset] == ' ')
+		result->offset++;
+}
+
+static bool call_prefix_handler(struct hfp_gw *hfp, const char *data)
+{
+	struct cmd_handler *handler;
+	const char *separators = ";?=\0";
+	struct hfp_gw_result result;
+	enum hfp_gw_cmd_type type;
+	char lookup_prefix[18];
+	uint8_t pref_len = 0;
+	const char *prefix;
+	int i;
+
+	result.offset = 0;
+	result.data = data;
+
+	skip_whitespace(&result);
+
+	if (strlen(data + result.offset) < 3)
+		return false;
+
+	if (strncmp(data + result.offset, "AT", 2))
+		if (strncmp(data + result.offset, "at", 2))
+			return false;
+
+	result.offset += 2;
+	prefix = data + result.offset;
+
+	if (isalpha(prefix[0])) {
+		lookup_prefix[pref_len++] = toupper(prefix[0]);
+	} else {
+		pref_len = strcspn(prefix, separators);
+		if (pref_len > 17 || pref_len < 2)
+			return false;
+
+		for (i = 0; i < pref_len; i++)
+			lookup_prefix[i] = toupper(prefix[i]);
+	}
+
+	lookup_prefix[pref_len] = '\0';
+	result.offset += pref_len;
+
+	if (lookup_prefix[0] == 'D') {
+		type = HFP_GW_CMD_TYPE_SET;
+		goto done;
+	}
+
+	if (data[result.offset] == '=') {
+		result.offset++;
+		if (data[result.offset] == '?') {
+			result.offset++;
+			type = HFP_GW_CMD_TYPE_TEST;
+		} else {
+			type = HFP_GW_CMD_TYPE_SET;
+		}
+		goto done;
+	}
+
+	if (data[result.offset] == '?') {
+		result.offset++;
+		type = HFP_GW_CMD_TYPE_READ;
+		goto done;
+	}
+
+	type = HFP_GW_CMD_TYPE_COMMAND;
+
+done:
+
+	handler = queue_find(hfp->cmd_handlers, match_handler_prefix,
+								lookup_prefix);
+	if (!handler)
+		return false;
+
+	handler->callback(&result, type, handler->user_data);
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
@@ -162,10 +250,12 @@ static void process_input(struct hfp_gw *hfp)
 
 	hfp->result_pending = true;
 
-	if (hfp->command_callback)
-		hfp->command_callback(str, hfp->command_data);
-	else
-		hfp_gw_send_result(hfp, HFP_RESULT_ERROR);
+	if (!call_prefix_handler(hfp, str)) {
+		if (hfp->command_callback)
+			hfp->command_callback(str, hfp->command_data);
+		else
+			hfp_gw_send_result(hfp, HFP_RESULT_ERROR);
+	}
 
 	len = ringbuf_drain(hfp->read_buf, count + 1);
 
-- 
1.8.3.1


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

* [PATCHv4 3/6] shared/hfp: Add get_number implementation
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 2/6] shared/hfp: Add implementiation of processing commands Marcin Kraglak
@ 2014-03-01 20:00 ` Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 4/6] shared/hfp: Add open/close container function Marcin Kraglak
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

User can call this function with hfp_gw_result, which will
be passed to prefix handler.
---
 src/shared/hfp.c | 31 +++++++++++++++++++++++++++++++
 src/shared/hfp.h |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 945f36e..7cc9a30 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -218,6 +218,37 @@ done:
 	return true;
 }
 
+static void next_field(struct hfp_gw_result *result)
+{
+	if (result->data[result->offset] == ',')
+		result->offset++;
+}
+
+bool hfp_gw_result_get_number(struct hfp_gw_result *result, unsigned int *val)
+{
+	int tmp = 0;
+	int i;
+
+	skip_whitespace(result);
+
+	i = result->offset;
+
+	while (result->data[i] >= '0' && result->data[i] <= '9')
+		tmp = tmp * 10 + result->data[i++] - '0';
+
+	if (i == result->offset)
+		return false;
+
+	if (val)
+		*val = tmp;
+	result->offset = i;
+
+	skip_whitespace(result);
+	next_field(result);
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 0755a46..40adcb6 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -112,3 +112,5 @@ bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
 						void *user_data,
 						hfp_destroy_func_t destroy);
 bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);
+
+bool hfp_gw_result_get_number(struct hfp_gw_result *result, unsigned int *val);
-- 
1.8.3.1


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

* [PATCHv4 4/6] shared/hfp: Add open/close container function
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 2/6] shared/hfp: Add implementiation of processing commands Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 3/6] shared/hfp: Add get_number implementation Marcin Kraglak
@ 2014-03-01 20:00 ` Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 5/6] shared/hfp: Add function to get string Marcin Kraglak
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

It will look for "(" or ")" parenthesis and skip it if found.
---
 src/shared/hfp.c | 26 ++++++++++++++++++++++++++
 src/shared/hfp.h |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 7cc9a30..d7cca32 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -249,6 +249,32 @@ bool hfp_gw_result_get_number(struct hfp_gw_result *result, unsigned int *val)
 	return true;
 }
 
+bool hfp_gw_result_open_container(struct hfp_gw_result *result)
+{
+	skip_whitespace(result);
+
+	/* The list shall be preceded by a left parenthesis "(") */
+	if (result->data[result->offset] != '(')
+		return false;
+
+	result->offset++;
+
+	return true;
+}
+
+bool hfp_gw_result_close_container(struct hfp_gw_result *result)
+{
+	skip_whitespace(result);
+
+	/* The list shall be followed by a right parenthesis (")" V250 5.7.3.1*/
+	if (result->data[result->offset] != ')')
+		return false;
+
+	result->offset++;
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 40adcb6..00905de 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -114,3 +114,5 @@ bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
 bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);
 
 bool hfp_gw_result_get_number(struct hfp_gw_result *result, unsigned int *val);
+bool hfp_gw_result_open_container(struct hfp_gw_result *result);
+bool hfp_gw_result_close_container(struct hfp_gw_result *result);
-- 
1.8.3.1


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

* [PATCHv4 5/6] shared/hfp: Add function to get string
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
                   ` (2 preceding siblings ...)
  2014-03-01 20:00 ` [PATCHv4 4/6] shared/hfp: Add open/close container function Marcin Kraglak
@ 2014-03-01 20:00 ` Marcin Kraglak
  2014-03-01 20:00 ` [PATCHv4 6/6] shared/hfp: Add function to get unquoted string Marcin Kraglak
  2014-03-01 20:37 ` [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Szymon Janc
  5 siblings, 0 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

It will look for quoted sting and write it to given buffer.
---
 src/shared/hfp.c | 33 +++++++++++++++++++++++++++++++++
 src/shared/hfp.h |  2 ++
 2 files changed, 35 insertions(+)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index d7cca32..10734fc 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -275,6 +275,39 @@ bool hfp_gw_result_close_container(struct hfp_gw_result *result)
 	return true;
 }
 
+bool hfp_gw_result_get_string(struct hfp_gw_result *result, char *buf,
+								uint8_t len)
+{
+	int i = 0;
+	const char *data = result->data;
+
+	skip_whitespace(result);
+
+	if (data[result->offset] != '"')
+		return false;
+
+	result->offset++;
+
+	while (data[result->offset] != '\0' && data[result->offset] != '"') {
+		if (i < len)
+			buf[i++] = data[result->offset];
+		result->offset++;
+	}
+
+	if (i < len)
+		buf[i++] = '\0';
+
+	if (data[result->offset] == '"')
+		result->offset++;
+	else
+		return false;
+
+	skip_whitespace(result);
+	next_field(result);
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 00905de..3313d91 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -116,3 +116,5 @@ bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);
 bool hfp_gw_result_get_number(struct hfp_gw_result *result, unsigned int *val);
 bool hfp_gw_result_open_container(struct hfp_gw_result *result);
 bool hfp_gw_result_close_container(struct hfp_gw_result *result);
+bool hfp_gw_result_get_string(struct hfp_gw_result *result, char *buf,
+								uint8_t len);
-- 
1.8.3.1


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

* [PATCHv4 6/6] shared/hfp: Add function to get unquoted string
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
                   ` (3 preceding siblings ...)
  2014-03-01 20:00 ` [PATCHv4 5/6] shared/hfp: Add function to get string Marcin Kraglak
@ 2014-03-01 20:00 ` Marcin Kraglak
  2014-03-01 20:37 ` [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Szymon Janc
  5 siblings, 0 replies; 7+ messages in thread
From: Marcin Kraglak @ 2014-03-01 20:00 UTC (permalink / raw)
  To: linux-bluetooth

---
 src/shared/hfp.c | 28 ++++++++++++++++++++++++++++
 src/shared/hfp.h |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/src/shared/hfp.c b/src/shared/hfp.c
index 10734fc..b10316e 100644
--- a/src/shared/hfp.c
+++ b/src/shared/hfp.c
@@ -308,6 +308,34 @@ bool hfp_gw_result_get_string(struct hfp_gw_result *result, char *buf,
 	return true;
 }
 
+bool hfp_gw_result_get_unquoted_string(struct hfp_gw_result *result, char *buf,
+								uint8_t len)
+{
+	const char *data = result->data;
+	int i = 0;
+	char c;
+
+	skip_whitespace(result);
+
+	c = data[result->offset];
+	if (c == '"' || c == ')' || c == '(')
+		return false;
+
+	while (data[result->offset] != '\0' && data[result->offset] != ','
+					&& data[result->offset] != ')') {
+		if (i < len)
+			buf[i++] = data[result->offset];
+		result->offset++;
+	}
+
+	if (i < len)
+		buf[i++] = '\0';
+
+	next_field(result);
+
+	return true;
+}
+
 static void process_input(struct hfp_gw *hfp)
 {
 	char *str, *ptr;
diff --git a/src/shared/hfp.h b/src/shared/hfp.h
index 3313d91..649b77e 100644
--- a/src/shared/hfp.h
+++ b/src/shared/hfp.h
@@ -118,3 +118,5 @@ bool hfp_gw_result_open_container(struct hfp_gw_result *result);
 bool hfp_gw_result_close_container(struct hfp_gw_result *result);
 bool hfp_gw_result_get_string(struct hfp_gw_result *result, char *buf,
 								uint8_t len);
+bool hfp_gw_result_get_unquoted_string(struct hfp_gw_result *result, char *buf,
+								uint8_t len);
-- 
1.8.3.1


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

* Re: [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality
  2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
                   ` (4 preceding siblings ...)
  2014-03-01 20:00 ` [PATCHv4 6/6] shared/hfp: Add function to get unquoted string Marcin Kraglak
@ 2014-03-01 20:37 ` Szymon Janc
  5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2014-03-01 20:37 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Saturday 01 of March 2014 21:00:41 Marcin Kraglak wrote:
> Add two functions: hfp_gw_register_prefix_handler() and
> hfp_gw_unregister_prefix_handler(). It will allow user to register for
> specific command. Current implementation just put/remove handler data
> from queue.
> ---
>  Makefile.tools   |  1 +
>  src/shared/hfp.c | 99
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/shared/hfp.h |
> 18 +++++++++++
>  3 files changed, 118 insertions(+)
> 
> diff --git a/Makefile.tools b/Makefile.tools
> index 9f7ba9f..31e1093 100644
> --- a/Makefile.tools
> +++ b/Makefile.tools
> @@ -63,6 +63,7 @@ emulator_hfp_SOURCES = emulator/hfp.c \
>  				monitor/mainloop.h monitor/mainloop.c \
>  				src/shared/io.h src/shared/io-mainloop.c \
>  				src/shared/util.h src/shared/util.c \
> +				src/shared/queue.h src/shared/queue.c \
>  				src/shared/ringbuf.h src/shared/ringbuf.c \
>  				src/shared/hfp.h src/shared/hfp.c
> 
> diff --git a/src/shared/hfp.c b/src/shared/hfp.c
> index 854cf46..4bf993d 100644
> --- a/src/shared/hfp.c
> +++ b/src/shared/hfp.c
> @@ -32,6 +32,7 @@
> 
>  #include "src/shared/util.h"
>  #include "src/shared/ringbuf.h"
> +#include "src/shared/queue.h"
>  #include "src/shared/io.h"
>  #include "src/shared/hfp.h"
> 
> @@ -42,6 +43,7 @@ struct hfp_gw {
>  	struct io *io;
>  	struct ringbuf *read_buf;
>  	struct ringbuf *write_buf;
> +	struct queue *cmd_handlers;
>  	bool writer_active;
>  	bool permissive_syntax;
>  	bool result_pending;
> @@ -60,6 +62,37 @@ struct hfp_gw {
>  	bool destroyed;
>  };
> 
> +struct cmd_handler {
> +	char *prefix;
> +	void *user_data;
> +	hfp_destroy_func_t destroy;
> +	hfp_result_func_t callback;
> +};
> +
> +static void destroy_cmd_handler(void *data)
> +{
> +	struct cmd_handler *handler = data;
> +
> +	if (handler->destroy)
> +		handler->destroy(handler->user_data);
> +
> +	free(handler);
> +}
> +
> +static bool match_handler_prefix(const void *a, const void *b)
> +{
> +	const struct cmd_handler *handler = a;
> +	const char *prefix = b;
> +
> +	if (strlen(handler->prefix) != strlen(prefix))
> +		return false;
> +
> +	if (memcmp(handler->prefix, prefix, strlen(prefix)))
> +		return false;
> +
> +	return true;
> +}
> +
>  static void write_watch_destroy(void *user_data)
>  {
>  	struct hfp_gw *hfp = user_data;
> @@ -196,8 +229,19 @@ struct hfp_gw *hfp_gw_new(int fd)
>  		return NULL;
>  	}
> 
> +	hfp->cmd_handlers = queue_new();
> +	if (!hfp->cmd_handlers) {
> +		io_destroy(hfp->io);
> +		ringbuf_free(hfp->write_buf);
> +		ringbuf_free(hfp->read_buf);
> +		free(hfp);
> +		return NULL;
> +	}
> +
>  	if (!io_set_read_handler(hfp->io, can_read_data,
>  					hfp, read_watch_destroy)) {
> +		queue_destroy(hfp->cmd_handlers,
> +						destroy_cmd_handler);
>  		io_destroy(hfp->io);
>  		ringbuf_free(hfp->write_buf);
>  		ringbuf_free(hfp->read_buf);
> @@ -250,6 +294,9 @@ void hfp_gw_unref(struct hfp_gw *hfp)
>  	ringbuf_free(hfp->write_buf);
>  	hfp->write_buf = NULL;
> 
> +	queue_destroy(hfp->cmd_handlers, destroy_cmd_handler);
> +	hfp->cmd_handlers = NULL;
> +
>  	if (!hfp->in_disconnect) {
>  		free(hfp);
>  		return;
> @@ -405,6 +452,58 @@ bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
>  	return true;
>  }
> 
> +bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
> +						const char *prefix,
> +						void *user_data,
> +						hfp_destroy_func_t destroy)
> +{
> +	struct cmd_handler *handler;
> +
> +	handler = new0(struct cmd_handler, 1);
> +	if (!handler)
> +		return false;
> +
> +	handler->callback = callback;
> +	handler->user_data = user_data;
> +
> +	handler->prefix = strdup(prefix);
> +	if (!handler->prefix) {
> +		free(handler);
> +		return false;
> +	}
> +
> +	if (queue_find(hfp->cmd_handlers, match_handler_prefix,
> +							handler->prefix)) {
> +		destroy_cmd_handler(handler);
> +		return false;
> +	}
> +
> +	handler->destroy = destroy;
> +
> +	return queue_push_tail(hfp->cmd_handlers, handler);
> +}
> +
> +bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix)
> +{
> +	struct cmd_handler *handler;
> +	char *lookup_prefix;
> +
> +	lookup_prefix = strdup(prefix);
> +	if (!lookup_prefix)
> +		return false;
> +
> +	handler = queue_remove_if(hfp->cmd_handlers, match_handler_prefix,
> +								lookup_prefix);
> +	free(lookup_prefix);
> +
> +	if (!handler)
> +		return false;
> +
> +	destroy_cmd_handler(handler);
> +
> +	return true;
> +}
> +
>  static void disconnect_watch_destroy(void *user_data)
>  {
>  	struct hfp_gw *hfp = user_data;
> diff --git a/src/shared/hfp.h b/src/shared/hfp.h
> index b0bd934..0755a46 100644
> --- a/src/shared/hfp.h
> +++ b/src/shared/hfp.h
> @@ -60,6 +60,18 @@ enum hfp_error {
>  	HFP_ERROR_NETWORK_NOT_ALLOWED		= 32,
>  };
> 
> +enum hfp_gw_cmd_type {
> +	HFP_GW_CMD_TYPE_READ,
> +	HFP_GW_CMD_TYPE_SET,
> +	HFP_GW_CMD_TYPE_TEST,
> +	HFP_GW_CMD_TYPE_COMMAND
> +};
> +
> +struct hfp_gw_result;
> +
> +typedef void (*hfp_result_func_t)(struct hfp_gw_result *result,
> +				enum hfp_gw_cmd_type type, void *user_data);
> +
>  typedef void (*hfp_destroy_func_t)(void *user_data);
>  typedef void (*hfp_debug_func_t)(const char *str, void *user_data);
> 
> @@ -94,3 +106,9 @@ bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
>  					hfp_destroy_func_t destroy);
> 
>  bool hfp_gw_disconnect(struct hfp_gw *hfp);
> +
> +bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
> +						const char *prefix,
> +						void *user_data,
> +						hfp_destroy_func_t destroy);
> +bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix);

All patches in this set are now applied, thanks.

-- 
BR
Szymon Janc

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

end of thread, other threads:[~2014-03-01 20:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-01 20:00 [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Marcin Kraglak
2014-03-01 20:00 ` [PATCHv4 2/6] shared/hfp: Add implementiation of processing commands Marcin Kraglak
2014-03-01 20:00 ` [PATCHv4 3/6] shared/hfp: Add get_number implementation Marcin Kraglak
2014-03-01 20:00 ` [PATCHv4 4/6] shared/hfp: Add open/close container function Marcin Kraglak
2014-03-01 20:00 ` [PATCHv4 5/6] shared/hfp: Add function to get string Marcin Kraglak
2014-03-01 20:00 ` [PATCHv4 6/6] shared/hfp: Add function to get unquoted string Marcin Kraglak
2014-03-01 20:37 ` [PATCHv4 1/6] shared/hfp: Add prefix handlers functionality Szymon Janc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox