All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] Improvements on gatttool interactive interface
@ 2013-03-21 22:31 Alvaro Silva
  2013-03-21 22:31 ` [PATCH 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
                   ` (13 more replies)
  0 siblings, 14 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

Hi,

This series implements some changes on gatttool in order to keep it
consistent with bluetoothctl approach, like colored prompt and not
breaking empty line upon pressing enter. In addition, some fixes were
made when displaying messages.

BR,
Alvaro Silva

Alvaro Silva (3):
  gatttool: Show connection state using color
  gatttool: Remove connecting message from prompt
  gatttool: Use error message prefixes consistently

Eder Ruiz Maria (9):
  gatttool: Remove programming error check
  gatttool: Remote address is mandatory for non-interactive gatttool
  gatttool: Use GError to propage error messages to caller
  gatttool: Fix issues with printf() and readline prompt
  gatttool: Replace more usages of printf() with rl_printf()
  gatttool: Use bluetoothctl behavior when pressing Enter on empty
    prompt
  gatttool: Use bluetoothctl strategy to handle standard input
  gatttool: Use bluetoothctl strategy for unix signal handling
  gatttool: Show info message when no primary service is found

Jefferson Delfes (1):
  gatttool: Fix memory leak after parsing input line

 Makefile.tools       |    3 +-
 attrib/gatttool.c    |   12 +-
 attrib/gatttool.h    |    3 +-
 attrib/interactive.c |  345 +++++++++++++++++++++++++++++++++-----------------
 attrib/utils.c       |   19 +--
 client/display.h     |    1 +
 6 files changed, 250 insertions(+), 133 deletions(-)

-- 
1.7.9.5


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

* [PATCH 01/13] gatttool: Fix memory leak after parsing input line
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 02/13] gatttool: Remove programming error check Alvaro Silva
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

The callback is responsible for freeing input line buffer that comes
from rl_callback_handler_install().
---
 attrib/interactive.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index a99ad0a..9f72453 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -850,7 +850,7 @@ static void parse_line(char *line_read)
 	line_read = g_strstrip(line_read);
 
 	if (*line_read == '\0')
-		return;
+		goto done;
 
 	add_history(line_read);
 
@@ -866,6 +866,9 @@ static void parse_line(char *line_read)
 		printf("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
+
+done:
+	free(line_read);
 }
 
 static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
-- 
1.7.9.5


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

* [PATCH 02/13] gatttool: Remove programming error check
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
  2013-03-21 22:31 ` [PATCH 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-22  1:06   ` Anderson Lizardo
  2013-03-21 22:31 ` [PATCH 03/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

---
 attrib/utils.c |    5 -----
 1 file changed, 5 deletions(-)

diff --git a/attrib/utils.c b/attrib/utils.c
index f9813d1..c8c8651 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -50,11 +50,6 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 	GError *err = NULL;
 	BtIOSecLevel sec;
 
-	/* Remote device */
-	if (dst == NULL) {
-		g_printerr("Remote Bluetooth address required\n");
-		return NULL;
-	}
 	str2ba(dst, &dba);
 
 	/* Local adapter */
-- 
1.7.9.5


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

* [PATCH 03/13] gatttool: Remote address is mandatory for non-interactive gatttool
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
  2013-03-21 22:31 ` [PATCH 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
  2013-03-21 22:31 ` [PATCH 02/13] gatttool: Remove programming error check Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

For gatttool non-interactive mode, command line parameter with
bluetooth remote address is mandatory.
---
 attrib/gatttool.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 29e3261..1dd0c35 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -603,6 +603,12 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
+	if (opt_dst == NULL) {
+		g_print("Remote Bluetooth address required\n");
+		got_error = TRUE;
+		goto done;
+	}
+
 	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb);
 	if (chan == NULL) {
-- 
1.7.9.5


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

* [PATCH 04/13] gatttool: Use GError to propage error messages to caller
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (2 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 03/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Handle runtime errors outside gatt_connect(), using GError to propagate
error messages to caller.
---
 attrib/gatttool.c    |    6 +++++-
 attrib/gatttool.h    |    3 ++-
 attrib/interactive.c |   10 +++++++---
 attrib/utils.c       |   14 +++++++-------
 4 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1dd0c35..8dbebbb 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -576,6 +576,7 @@ int main(int argc, char *argv[])
 	if (g_option_context_parse(context, &argc, &argv, &gerr) == FALSE) {
 		g_printerr("%s\n", gerr->message);
 		g_error_free(gerr);
+		gerr = NULL;
 	}
 
 	if (opt_interactive) {
@@ -610,8 +611,11 @@ int main(int argc, char *argv[])
 	}
 
 	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb);
+					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
+		g_printerr("%s\n", gerr->message);
+		g_error_free(gerr);
+		gerr = NULL;
 		got_error = TRUE;
 		goto done;
 	}
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index a38339b..0e13739 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -25,5 +25,6 @@ int interactive(const gchar *src, const gchar *dst, const gchar *dst_type,
 		gboolean le);
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 			const gchar *dst_type, const gchar *sec_level,
-			int psm, int mtu, BtIOConnect connect_cb);
+			int psm, int mtu, BtIOConnect connect_cb,
+			GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9f72453..ce35218 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -395,6 +395,8 @@ static gboolean channel_watcher(GIOChannel *chan, GIOCondition cond,
 
 static void cmd_connect(int argcp, char **argvp)
 {
+	GError *gerr = NULL;
+
 	if (conn_state != STATE_DISCONNECTED)
 		return;
 
@@ -416,10 +418,12 @@ static void cmd_connect(int argcp, char **argvp)
 
 	set_state(STATE_CONNECTING);
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-						opt_psm, opt_mtu, connect_cb);
-	if (iochannel == NULL)
+					opt_psm, opt_mtu, connect_cb, &gerr);
+	if (iochannel == NULL) {
+		printf("%s\n", gerr->message);
 		set_state(STATE_DISCONNECTED);
-	else
+		g_error_free(gerr);
+	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
 }
 
diff --git a/attrib/utils.c b/attrib/utils.c
index c8c8651..e263bcb 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -42,12 +42,13 @@
 
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				const gchar *dst_type, const gchar *sec_level,
-				int psm, int mtu, BtIOConnect connect_cb)
+				int psm, int mtu, BtIOConnect connect_cb,
+				GError **gerr)
 {
 	GIOChannel *chan;
 	bdaddr_t sba, dba;
 	uint8_t dest_type;
-	GError *err = NULL;
+	GError *tmp_err = NULL;
 	BtIOSecLevel sec;
 
 	str2ba(dst, &dba);
@@ -75,7 +76,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 		sec = BT_IO_SEC_LOW;
 
 	if (psm == 0)
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_DEST_TYPE, dest_type,
@@ -83,7 +84,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 	else
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_PSM, psm,
@@ -91,9 +92,8 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 
-	if (err) {
-		g_printerr("%s\n", err->message);
-		g_error_free(err);
+	if (tmp_err) {
+		g_propagate_error(gerr, tmp_err);
 		return NULL;
 	}
 
-- 
1.7.9.5


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

* [PATCH 05/13] gatttool: Fix issues with printf() and readline prompt
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (3 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Use rl_printf() from bluetoothctl to consistently display messages. This
is specially important for asynchronous callbacks, where using printf()
may mess up the prompt created by readline.
---
 Makefile.tools       |    3 ++-
 attrib/interactive.c |    9 +++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 4d45682..0de0a0d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -189,7 +189,8 @@ noinst_PROGRAMS += attrib/gatttool \
 attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
 				attrib/gattrib.c btio/btio.c \
 				attrib/gatttool.h attrib/interactive.c \
-				attrib/utils.c src/log.c
+				attrib/utils.c src/log.c client/display.c \
+				client/display.h
 attrib_gatttool_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@ -lreadline
 
 tools_obex_client_tool_SOURCES = $(gobex_sources) $(btio_sources) \
diff --git a/attrib/interactive.c b/attrib/interactive.c
index ce35218..d5da9ad 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -40,6 +40,7 @@
 #include "gattrib.h"
 #include "gatt.h"
 #include "gatttool.h"
+#include "client/display.h"
 
 static GIOChannel *iochannel = NULL;
 static GAttrib *attrib = NULL;
@@ -102,7 +103,6 @@ static void set_state(enum state st)
 {
 	conn_state = st;
 	rl_set_prompt(get_prompt());
-	rl_redisplay();
 }
 
 static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
@@ -145,8 +145,8 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	if (err) {
-		printf("connect error: %s\n", err->message);
 		set_state(STATE_DISCONNECTED);
+		rl_printf("%s\n", err->message);
 		return;
 	}
 
@@ -156,6 +156,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
 						events_handler, attrib, NULL);
 	set_state(STATE_CONNECTED);
+	rl_redisplay();
 }
 
 static void disconnect_io()
@@ -412,7 +413,7 @@ static void cmd_connect(int argcp, char **argvp)
 	}
 
 	if (opt_dst == NULL) {
-		printf("Remote Bluetooth address required\n");
+		rl_printf("Remote Bluetooth address required\n");
 		return;
 	}
 
@@ -420,8 +421,8 @@ static void cmd_connect(int argcp, char **argvp)
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
-		printf("%s\n", gerr->message);
 		set_state(STATE_DISCONNECTED);
+		rl_printf("%s\n", gerr->message);
 		g_error_free(gerr);
 	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
-- 
1.7.9.5


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

* [PATCH 06/13] gatttool: Replace more usages of printf() with rl_printf()
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (4 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

rl_printf() works better with readline than plain printf(), specially on
asynchronous callbacks.
---
 attrib/interactive.c |  177 ++++++++++++++++++++++++--------------------------
 1 file changed, 84 insertions(+), 93 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index d5da9ad..4fd2280 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -110,27 +110,31 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	uint8_t *opdu;
 	uint16_t handle, i, olen;
 	size_t plen;
+	GString *s;
 
 	handle = att_get_u16(&pdu[1]);
 
-	printf("\n");
 	switch (pdu[0]) {
 	case ATT_OP_HANDLE_NOTIFY:
-		printf("Notification handle = 0x%04x value: ", handle);
+		s = g_string_new(NULL);
+		g_string_printf(s, "Notification handle = 0x%04x value: ",
+									handle);
 		break;
 	case ATT_OP_HANDLE_IND:
-		printf("Indication   handle = 0x%04x value: ", handle);
+		s = g_string_new(NULL);
+		g_string_printf(s, "Indication   handle = 0x%04x value: ",
+									handle);
 		break;
 	default:
-		printf("Invalid opcode\n");
+		rl_printf("Invalid opcode\n");
 		return;
 	}
 
 	for (i = 3; i < len; i++)
-		printf("%02x ", pdu[i]);
+		g_string_append_printf(s, "%02x ", pdu[i]);
 
-	printf("\n");
-	rl_forced_update_display();
+	rl_printf("%s\n", s->str);
+	g_string_free(s, TRUE);
 
 	if (pdu[0] == ATT_OP_HANDLE_NOTIFY)
 		return;
@@ -180,19 +184,16 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Discover all primary services failed: %s\n",
+		rl_printf("Discover all primary services failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = services; l; l = l->next) {
 		struct gatt_primary *prim = l->data;
-		printf("attr handle: 0x%04x, end grp handle: 0x%04x "
-			"uuid: %s\n", prim->range.start, prim->range.end, prim->uuid);
+		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
+				prim->range.start, prim->range.end, prim->uuid);
 	}
-
-	rl_forced_update_display();
 }
 
 static void primary_by_uuid_cb(GSList *ranges, guint8 status,
@@ -201,19 +202,16 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 	GSList *l;
 
 	if (status) {
-		printf("Discover primary services by UUID failed: %s\n",
+		rl_printf("Discover primary services by UUID failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = ranges; l; l = l->next) {
 		struct att_range *range = l->data;
-		g_print("Starting handle: 0x%04x Ending handle: 0x%04x\n",
+		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
 						range->start, range->end);
 	}
-
-	rl_forced_update_display();
 }
 
 static void included_cb(GSList *includes, guint8 status, gpointer user_data)
@@ -221,27 +219,23 @@ static void included_cb(GSList *includes, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Find included services failed: %s\n",
+		rl_printf("Find included services failed: %s\n",
 							att_ecode2str(status));
-		goto done;
+		return;
 	}
 
 	if (includes == NULL) {
-		printf("No included services found for this range\n");
-		goto done;
+		rl_printf("No included services found for this range\n");
+		return;
 	}
 
-	printf("\n");
 	for (l = includes; l; l = l->next) {
 		struct gatt_included *incl = l->data;
-		printf("handle: 0x%04x, start handle: 0x%04x, "
+		rl_printf("handle: 0x%04x, start handle: 0x%04x, "
 					"end handle: 0x%04x uuid: %s\n",
 					incl->handle, incl->range.start,
 					incl->range.end, incl->uuid);
 	}
-
-done:
-	rl_forced_update_display();
 }
 
 static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
@@ -249,22 +243,19 @@ static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Discover all characteristics failed: %s\n",
+		rl_printf("Discover all characteristics failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = characteristics; l; l = l->next) {
 		struct gatt_char *chars = l->data;
 
-		printf("handle: 0x%04x, char properties: 0x%02x, char value "
+		rl_printf("handle: 0x%04x, char properties: 0x%02x, char value "
 				"handle: 0x%04x, uuid: %s\n", chars->handle,
 				chars->properties, chars->value_handle,
 				chars->uuid);
 	}
-
-	rl_forced_update_display();
 }
 
 static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -276,7 +267,7 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	int i;
 
 	if (status != 0) {
-		printf("Discover descriptors finished: %s\n",
+		rl_printf("Discover descriptors finished: %s\n",
 						att_ecode2str(status));
 		return;
 	}
@@ -285,7 +276,6 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	if (list == NULL)
 		return;
 
-	printf("\n");
 	for (i = 0; i < list->num; i++) {
 		char uuidstr[MAX_LEN_UUID_STR];
 		uint8_t *value;
@@ -300,15 +290,13 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 			uuid = att_get_uuid128(&value[2]);
 
 		bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
-		printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
+		rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
 	}
 
 	att_data_list_free(list);
 
 	if (handle != 0xffff && handle < end)
 		gatt_find_info(attrib, handle + 1, end, char_desc_cb, NULL);
-	else
-		rl_forced_update_display();
 }
 
 static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -317,25 +305,26 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint8_t value[plen];
 	ssize_t vlen;
 	int i;
+	GString *s;
 
 	if (status != 0) {
-		printf("Characteristic value/descriptor read failed: %s\n",
+		rl_printf("Characteristic value/descriptor read failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
 	if (vlen < 0) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
-	printf("\nCharacteristic value/descriptor: ");
+	s = g_string_new("Characteristic value/descriptor: ");
 	for (i = 0; i < vlen; i++)
-		printf("%02x ", value[i]);
-	printf("\n");
+		g_string_append_printf(s, "%02x ", value[i]);
 
-	rl_forced_update_display();
+	rl_printf("%s\n", s->str);
+	g_string_free(s, TRUE);
 }
 
 static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
@@ -344,13 +333,14 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 	struct characteristic_data *char_data = user_data;
 	struct att_data_list *list;
 	int i;
+	GString *s;
 
 	if (status == ATT_ECODE_ATTR_NOT_FOUND &&
 				char_data->start != char_data->orig_start)
 		goto done;
 
 	if (status != 0) {
-		printf("Read characteristics by UUID failed: %s\n",
+		rl_printf("Read characteristics by UUID failed: %s\n",
 							att_ecode2str(status));
 		goto done;
 	}
@@ -359,22 +349,23 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 	if (list == NULL)
 		goto done;
 
+	s = g_string_new(NULL);
 	for (i = 0; i < list->num; i++) {
 		uint8_t *value = list->data[i];
 		int j;
 
 		char_data->start = att_get_u16(value) + 1;
-
-		printf("\nhandle: 0x%04x \t value: ", att_get_u16(value));
+		g_string_printf(s, "handle: 0x%04x \t value: ",
+							att_get_u16(value));
 		value += 2;
 		for (j = 0; j < list->len - 2; j++, value++)
-			printf("%02x ", *value);
-		printf("\n");
+			g_string_append_printf(s, "%02x ", *value);
+
+		rl_printf("%s\n", s->str);
 	}
 
 	att_data_list_free(list);
-
-	rl_forced_update_display();
+	g_string_free(s, TRUE);
 
 done:
 	g_free(char_data);
@@ -438,7 +429,7 @@ static void cmd_primary(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
@@ -448,7 +439,7 @@ static void cmd_primary(int argcp, char **argvp)
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		printf("Invalid UUID\n");
+		rl_printf("Invalid UUID\n");
 		return;
 	}
 
@@ -474,14 +465,14 @@ static void cmd_included(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 		end = start;
@@ -490,7 +481,7 @@ static void cmd_included(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -504,14 +495,14 @@ static void cmd_char(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -519,7 +510,7 @@ static void cmd_char(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -528,7 +519,7 @@ static void cmd_char(int argcp, char **argvp)
 		bt_uuid_t uuid;
 
 		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
-			printf("Invalid UUID\n");
+			rl_printf("Invalid UUID\n");
 			return;
 		}
 
@@ -542,14 +533,14 @@ static void cmd_char(int argcp, char **argvp)
 static void cmd_char_desc(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	} else
@@ -558,7 +549,7 @@ static void cmd_char_desc(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	} else
@@ -572,18 +563,18 @@ static void cmd_read_hnd(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Missing argument: handle\n");
+		rl_printf("Missing argument: handle\n");
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle < 0) {
-		printf("Invalid handle: %s\n", argvp[1]);
+		rl_printf("Invalid handle: %s\n", argvp[1]);
 		return;
 	}
 
@@ -598,24 +589,24 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Missing argument: UUID\n");
+		rl_printf("Missing argument: UUID\n");
 		return;
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		printf("Invalid UUID\n");
+		rl_printf("Invalid UUID\n");
 		return;
 	}
 
 	if (argcp > 2) {
 		start = strtohandle(argvp[2]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -623,7 +614,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	if (argcp > 3) {
 		end = strtohandle(argvp[3]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -642,17 +633,17 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
 	if (status != 0) {
-		printf("Characteristic Write Request failed: "
+		rl_printf("Characteristic Write Request failed: "
 						"%s\n", att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
-	printf("Characteristic value was written successfully\n");
+	rl_printf("Characteristic value was written successfully\n");
 }
 
 static void cmd_char_write(int argcp, char **argvp)
@@ -662,24 +653,24 @@ static void cmd_char_write(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 3) {
-		printf("Usage: %s <handle> <new value>\n", argvp[0]);
+		rl_printf("Usage: %s <handle> <new value>\n", argvp[0]);
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle <= 0) {
-		printf("A valid handle is required\n");
+		rl_printf("A valid handle is required\n");
 		return;
 	}
 
 	plen = gatt_attr_data_from_string(argvp[2], &value);
 	if (plen == 0) {
-		g_printerr("Invalid value\n");
+		rl_printf("Invalid value\n");
 		return;
 	}
 
@@ -698,7 +689,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 	BtIOSecLevel sec_level;
 
 	if (argcp < 2) {
-		printf("sec-level: %s\n", opt_sec_level);
+		rl_printf("sec-level: %s\n", opt_sec_level);
 		return;
 	}
 
@@ -709,7 +700,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 	else if (strcasecmp(argvp[1], "low") == 0)
 		sec_level = BT_IO_SEC_LOW;
 	else {
-		printf("Allowed values: low | medium | high\n");
+		rl_printf("Allowed values: low | medium | high\n");
 		return;
 	}
 
@@ -720,7 +711,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 		return;
 
 	if (opt_psm) {
-		printf("It must be reconnected to this change take effect\n");
+		rl_printf("Change will take effect on reconnection\n");
 		return;
 	}
 
@@ -728,7 +719,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 			BT_IO_OPT_SEC_LEVEL, sec_level,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
-		printf("Error: %s\n", gerr->message);
+		rl_printf("Error: %s\n", gerr->message);
 		g_error_free(gerr);
 	}
 }
@@ -739,44 +730,44 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint16_t mtu;
 
 	if (status != 0) {
-		printf("Exchange MTU Request failed: %s\n",
+		rl_printf("Exchange MTU Request failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_mtu_resp(pdu, plen, &mtu)) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
 	mtu = MIN(mtu, opt_mtu);
 	/* Set new value for MTU in client */
 	if (g_attrib_set_mtu(attrib, mtu))
-		printf("MTU was exchanged successfully: %d\n", mtu);
+		rl_printf("MTU was exchanged successfully: %d\n", mtu);
 	else
-		printf("Error exchanging MTU\n");
+		rl_printf("Error exchanging MTU\n");
 }
 
 static void cmd_mtu(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: not connected.\n");
+		rl_printf("Command failed: not connected.\n");
 		return;
 	}
 
 	if (opt_psm) {
-		printf("Command failed: operation is only available for LE"
+		rl_printf("Command failed: operation is only available for LE"
 							" transport.\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Usage: mtu <value>\n");
+		rl_printf("Usage: mtu <value>\n");
 		return;
 	}
 
 	if (opt_mtu) {
-		printf("Command failed: MTU exchange can only occur once per"
+		rl_printf("Command failed: MTU exchange can only occur once per"
 							" connection.\n");
 		return;
 	}
@@ -784,7 +775,7 @@ static void cmd_mtu(int argcp, char **argvp)
 	errno = 0;
 	opt_mtu = strtoll(argvp[1], NULL, 0);
 	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
-		printf("Invalid value. Minimum MTU size is %d\n",
+		rl_printf("Invalid value. Minimum MTU size is %d\n",
 							ATT_DEFAULT_LE_MTU);
 		return;
 	}
@@ -836,7 +827,7 @@ static void cmd_help(int argcp, char **argvp)
 	int i;
 
 	for (i = 0; commands[i].cmd; i++)
-		printf("%-15s %-30s %s\n", commands[i].cmd,
+		rl_printf("%-15s %-30s %s\n", commands[i].cmd,
 				commands[i].params, commands[i].desc);
 }
 
@@ -847,7 +838,7 @@ static void parse_line(char *line_read)
 	int i;
 
 	if (line_read == NULL) {
-		printf("\n");
+		rl_printf("\n");
 		cmd_exit(0, NULL);
 		return;
 	}
@@ -868,7 +859,7 @@ static void parse_line(char *line_read)
 	if (commands[i].cmd)
 		commands[i].func(argcp, argvp);
 	else
-		printf("%s: command not found\n", argvp[0]);
+		rl_printf("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
 
-- 
1.7.9.5


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

* [PATCH 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (5 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 08/13] gatttool: Show connection state using color Alvaro Silva
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

---
 attrib/interactive.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 4fd2280..ecb8b7d 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -930,6 +930,7 @@ int interactive(const gchar *src, const gchar *dst,
 	g_io_add_watch(pchan, events, prompt_read, NULL);
 
 	rl_attempted_completion_function = commands_completion;
+	rl_erase_empty_line = 1;
 	rl_callback_handler_install(get_prompt(), parse_line);
 
 	g_main_loop_run(event_loop);
-- 
1.7.9.5


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

* [PATCH 08/13] gatttool: Show connection state using color
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (6 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

When device is connected, the Bluetooth address is shown in blue color.
---
 attrib/interactive.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index ecb8b7d..5ffe2fb 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -79,15 +79,15 @@ static char *get_prompt(void)
 	}
 
 	if (conn_state == STATE_CONNECTED)
-		g_string_assign(prompt, "[CON]");
-	else
-		g_string_assign(prompt, "[   ]");
+		g_string_append(prompt, COLOR_BLUE);
 
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
 		g_string_append_printf(prompt, "[%17s]", "");
 
+	g_string_append(prompt, COLOR_OFF);
+
 	if (opt_psm)
 		g_string_append(prompt, "[BR]");
 	else
-- 
1.7.9.5


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

* [PATCH 09/13] gatttool: Remove connecting message from prompt
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (7 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 08/13] gatttool: Show connection state using color Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

When trying to connect, the "connecting" message is not set as prompt
anymore. Instead, it is printed just like other status messages and the
prompt is kept, allowing the user to send commands while connection is
being established.
---
 attrib/interactive.c |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 5ffe2fb..7520324 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -73,20 +73,18 @@ static enum state {
 
 static char *get_prompt(void)
 {
-	if (conn_state == STATE_CONNECTING) {
-		g_string_assign(prompt, "Connecting... ");
-		return prompt->str;
-	}
-
 	if (conn_state == STATE_CONNECTED)
-		g_string_append(prompt, COLOR_BLUE);
+		g_string_assign(prompt, COLOR_BLUE);
+	else
+		g_string_assign(prompt, "");
 
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
 		g_string_append_printf(prompt, "[%17s]", "");
 
-	g_string_append(prompt, COLOR_OFF);
+	if (conn_state == STATE_CONNECTED)
+		g_string_append(prompt, COLOR_OFF);
 
 	if (opt_psm)
 		g_string_append(prompt, "[BR]");
@@ -160,7 +158,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
 						events_handler, attrib, NULL);
 	set_state(STATE_CONNECTED);
-	rl_redisplay();
+	rl_printf("Connection successful\n");
 }
 
 static void disconnect_io()
@@ -408,6 +406,7 @@ static void cmd_connect(int argcp, char **argvp)
 		return;
 	}
 
+	rl_printf("Attempting to connect to %s\n", opt_dst);
 	set_state(STATE_CONNECTING);
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb, &gerr);
-- 
1.7.9.5


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

* [PATCH 10/13] gatttool: Use bluetoothctl strategy to handle standard input
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (8 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Use GSource id returned by g_io_add_watch() instead of raw GIOChannel to
handle stdin and glib main loop.
---
 attrib/interactive.c |   26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 7520324..fa3f82a 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -906,11 +906,26 @@ static char **commands_completion(const char *text, int start, int end)
 		return NULL;
 }
 
+static guint setup_standard_input(void)
+{
+	GIOChannel *channel;
+	guint source;
+
+	channel = g_io_channel_unix_new(fileno(stdin));
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				prompt_read, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int interactive(const gchar *src, const gchar *dst,
 		const gchar *dst_type, int psm)
 {
-	GIOChannel *pchan;
-	gint events;
+	guint input;
 
 	opt_sec_level = g_strdup("low");
 
@@ -923,10 +938,7 @@ int interactive(const gchar *src, const gchar *dst,
 
 	event_loop = g_main_loop_new(NULL, FALSE);
 
-	pchan = g_io_channel_unix_new(fileno(stdin));
-	g_io_channel_set_close_on_unref(pchan, TRUE);
-	events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-	g_io_add_watch(pchan, events, prompt_read, NULL);
+	input = setup_standard_input();
 
 	rl_attempted_completion_function = commands_completion;
 	rl_erase_empty_line = 1;
@@ -936,7 +948,7 @@ int interactive(const gchar *src, const gchar *dst,
 
 	rl_callback_handler_remove();
 	cmd_disconnect(0, NULL);
-	g_io_channel_unref(pchan);
+	g_source_remove(input);
 	g_main_loop_unref(event_loop);
 	g_string_free(prompt, TRUE);
 
-- 
1.7.9.5


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

* [PATCH 11/13] gatttool: Use bluetoothctl strategy for unix signal handling
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (9 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Now to exit from gatttool at interactive mode, user must use SIGTERM(15)
or press Ctrl+D. SIGINT(2) or Ctrl+C just flushes typed characters and
breaks line.
---
 attrib/interactive.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index fa3f82a..9b16ddf 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -29,6 +29,9 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/signalfd.h>
 #include <glib.h>
 
 #include <readline/readline.h>
@@ -922,10 +925,88 @@ static guint setup_standard_input(void)
 	return source;
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+							gpointer user_data)
+{
+	static unsigned int __terminated = 0;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		g_main_loop_quit(event_loop);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+		rl_replace_line("", 0);
+		rl_crlf();
+		rl_on_new_line();
+		rl_redisplay();
+		break;
+	case SIGTERM:
+		if (__terminated == 0) {
+			rl_replace_line("", 0);
+			rl_crlf();
+			g_main_loop_quit(event_loop);
+		}
+
+		__terminated = 1;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int interactive(const gchar *src, const gchar *dst,
 		const gchar *dst_type, int psm)
 {
 	guint input;
+	guint signal;
 
 	opt_sec_level = g_strdup("low");
 
@@ -939,6 +1020,7 @@ int interactive(const gchar *src, const gchar *dst,
 	event_loop = g_main_loop_new(NULL, FALSE);
 
 	input = setup_standard_input();
+	signal = setup_signalfd();
 
 	rl_attempted_completion_function = commands_completion;
 	rl_erase_empty_line = 1;
@@ -949,6 +1031,7 @@ int interactive(const gchar *src, const gchar *dst,
 	rl_callback_handler_remove();
 	cmd_disconnect(0, NULL);
 	g_source_remove(input);
+	g_source_remove(signal);
 	g_main_loop_unref(event_loop);
 	g_string_free(prompt, TRUE);
 
-- 
1.7.9.5


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

* [PATCH 12/13] gatttool: Show info message when no primary service is found
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (10 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-03-21 22:31 ` [PATCH 13/13] gatttool: Use error message prefixes consistently Alvaro Silva
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

---
 attrib/interactive.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9b16ddf..1d31889 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -190,6 +190,11 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 		return;
 	}
 
+	if (services == NULL) {
+		rl_printf("No primary service found\n");
+		return;
+	}
+
 	for (l = services; l; l = l->next) {
 		struct gatt_primary *prim = l->data;
 		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
@@ -208,6 +213,11 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 		return;
 	}
 
+	if (ranges == NULL) {
+		rl_printf("No service UUID found\n");
+		return;
+	}
+
 	for (l = ranges; l; l = l->next) {
 		struct att_range *range = l->data;
 		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
-- 
1.7.9.5


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

* [PATCH 13/13] gatttool: Use error message prefixes consistently
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (11 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
@ 2013-03-21 22:31 ` Alvaro Silva
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
  13 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-03-21 22:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

Replace rl_printf() calls with macros that add appropriate prefixes.
---
 attrib/interactive.c |  107 ++++++++++++++++++++++++++------------------------
 client/display.h     |    1 +
 2 files changed, 57 insertions(+), 51 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 1d31889..6691f20 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -27,6 +27,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -74,6 +75,12 @@ static enum state {
 	STATE_CONNECTED
 } conn_state;
 
+#define error(fmt, arg...) \
+	rl_printf(COLOR_ERROR "Error: " COLOR_OFF fmt, ## arg)
+
+#define failed(fmt, arg...) \
+	rl_printf(COLOR_ERROR "Command Failed: " COLOR_OFF fmt, ## arg)
+
 static char *get_prompt(void)
 {
 	if (conn_state == STATE_CONNECTED)
@@ -127,7 +134,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 									handle);
 		break;
 	default:
-		rl_printf("Invalid opcode\n");
+		error("Invalid opcode\n");
 		return;
 	}
 
@@ -151,7 +158,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	if (err) {
 		set_state(STATE_DISCONNECTED);
-		rl_printf("%s\n", err->message);
+		error("%s\n", err->message);
 		return;
 	}
 
@@ -185,13 +192,13 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover all primary services failed: %s\n",
-							att_ecode2str(status));
+		error("Discover all primary services failed: %s\n",
+						att_ecode2str(status));
 		return;
 	}
 
 	if (services == NULL) {
-		rl_printf("No primary service found\n");
+		error("No primary service found\n");
 		return;
 	}
 
@@ -208,13 +215,13 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover primary services by UUID failed: %s\n",
+		error("Discover primary services by UUID failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	if (ranges == NULL) {
-		rl_printf("No service UUID found\n");
+		error("No service UUID found\n");
 		return;
 	}
 
@@ -230,7 +237,7 @@ static void included_cb(GSList *includes, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Find included services failed: %s\n",
+		error("Find included services failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
@@ -254,7 +261,7 @@ static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover all characteristics failed: %s\n",
+		error("Discover all characteristics failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
@@ -319,14 +326,14 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	GString *s;
 
 	if (status != 0) {
-		rl_printf("Characteristic value/descriptor read failed: %s\n",
+		error("Characteristic value/descriptor read failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
 	if (vlen < 0) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -351,7 +358,7 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 		goto done;
 
 	if (status != 0) {
-		rl_printf("Read characteristics by UUID failed: %s\n",
+		error("Read characteristics by UUID failed: %s\n",
 							att_ecode2str(status));
 		goto done;
 	}
@@ -415,7 +422,7 @@ static void cmd_connect(int argcp, char **argvp)
 	}
 
 	if (opt_dst == NULL) {
-		rl_printf("Remote Bluetooth address required\n");
+		error("Remote Bluetooth address required\n");
 		return;
 	}
 
@@ -425,7 +432,7 @@ static void cmd_connect(int argcp, char **argvp)
 					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
-		rl_printf("%s\n", gerr->message);
+		error("%s\n", gerr->message);
 		g_error_free(gerr);
 	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
@@ -441,7 +448,7 @@ static void cmd_primary(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
@@ -451,7 +458,7 @@ static void cmd_primary(int argcp, char **argvp)
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		rl_printf("Invalid UUID\n");
+		error("Invalid UUID\n");
 		return;
 	}
 
@@ -477,14 +484,14 @@ static void cmd_included(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 		end = start;
@@ -493,7 +500,7 @@ static void cmd_included(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -507,14 +514,14 @@ static void cmd_char(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -522,7 +529,7 @@ static void cmd_char(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -531,7 +538,7 @@ static void cmd_char(int argcp, char **argvp)
 		bt_uuid_t uuid;
 
 		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
-			rl_printf("Invalid UUID\n");
+			error("Invalid UUID\n");
 			return;
 		}
 
@@ -545,14 +552,14 @@ static void cmd_char(int argcp, char **argvp)
 static void cmd_char_desc(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	} else
@@ -561,7 +568,7 @@ static void cmd_char_desc(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	} else
@@ -575,18 +582,18 @@ static void cmd_read_hnd(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		rl_printf("Missing argument: handle\n");
+		error("Missing argument: handle\n");
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle < 0) {
-		rl_printf("Invalid handle: %s\n", argvp[1]);
+		error("Invalid handle: %s\n", argvp[1]);
 		return;
 	}
 
@@ -601,24 +608,24 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		rl_printf("Missing argument: UUID\n");
+		error("Missing argument: UUID\n");
 		return;
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		rl_printf("Invalid UUID\n");
+		error("Invalid UUID\n");
 		return;
 	}
 
 	if (argcp > 2) {
 		start = strtohandle(argvp[2]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -626,7 +633,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	if (argcp > 3) {
 		end = strtohandle(argvp[3]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -645,13 +652,13 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
 	if (status != 0) {
-		rl_printf("Characteristic Write Request failed: "
+		error("Characteristic Write Request failed: "
 						"%s\n", att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -665,7 +672,7 @@ static void cmd_char_write(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
@@ -676,13 +683,13 @@ static void cmd_char_write(int argcp, char **argvp)
 
 	handle = strtohandle(argvp[1]);
 	if (handle <= 0) {
-		rl_printf("A valid handle is required\n");
+		error("A valid handle is required\n");
 		return;
 	}
 
 	plen = gatt_attr_data_from_string(argvp[2], &value);
 	if (plen == 0) {
-		rl_printf("Invalid value\n");
+		error("Invalid value\n");
 		return;
 	}
 
@@ -731,7 +738,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 			BT_IO_OPT_SEC_LEVEL, sec_level,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
-		rl_printf("Error: %s\n", gerr->message);
+		error("%s\n", gerr->message);
 		g_error_free(gerr);
 	}
 }
@@ -742,13 +749,13 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint16_t mtu;
 
 	if (status != 0) {
-		rl_printf("Exchange MTU Request failed: %s\n",
-							att_ecode2str(status));
+		error("Exchange MTU Request failed: %s\n",
+						att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_mtu_resp(pdu, plen, &mtu)) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -757,19 +764,18 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	if (g_attrib_set_mtu(attrib, mtu))
 		rl_printf("MTU was exchanged successfully: %d\n", mtu);
 	else
-		rl_printf("Error exchanging MTU\n");
+		error("Error exchanging MTU\n");
 }
 
 static void cmd_mtu(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: not connected.\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (opt_psm) {
-		rl_printf("Command failed: operation is only available for LE"
-							" transport.\n");
+		failed("Operation is only available for LE transport.\n");
 		return;
 	}
 
@@ -779,15 +785,14 @@ static void cmd_mtu(int argcp, char **argvp)
 	}
 
 	if (opt_mtu) {
-		rl_printf("Command failed: MTU exchange can only occur once per"
-							" connection.\n");
+		failed("MTU exchange can only occur once per connection.\n");
 		return;
 	}
 
 	errno = 0;
 	opt_mtu = strtoll(argvp[1], NULL, 0);
 	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
-		rl_printf("Invalid value. Minimum MTU size is %d\n",
+		error("Invalid value. Minimum MTU size is %d\n",
 							ATT_DEFAULT_LE_MTU);
 		return;
 	}
@@ -871,7 +876,7 @@ static void parse_line(char *line_read)
 	if (commands[i].cmd)
 		commands[i].func(argcp, argvp);
 	else
-		rl_printf("%s: command not found\n", argvp[0]);
+		error("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
 
diff --git a/client/display.h b/client/display.h
index 393a3c8..9ddf6d0 100644
--- a/client/display.h
+++ b/client/display.h
@@ -23,5 +23,6 @@
 
 #define COLOR_OFF	"\x1B[0m"
 #define COLOR_BLUE	"\x1B[0;34m"
+#define COLOR_ERROR	"\x1B[0;31m"
 
 void rl_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
-- 
1.7.9.5


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

* Re: [PATCH 02/13] gatttool: Remove programming error check
  2013-03-21 22:31 ` [PATCH 02/13] gatttool: Remove programming error check Alvaro Silva
@ 2013-03-22  1:06   ` Anderson Lizardo
  0 siblings, 0 replies; 32+ messages in thread
From: Anderson Lizardo @ 2013-03-22  1:06 UTC (permalink / raw)
  To: Alvaro Silva; +Cc: linux-bluetooth, Eder Ruiz Maria

Hi,

On Thu, Mar 21, 2013 at 6:31 PM, Alvaro Silva
<alvaro.silva@openbossa.org> wrote:
> From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Just to clarify (IMHO the commit message is incomplete): this check is
removed here because it is more appropriate to be done by callers of
gatt_connect(). This is already done on interactive mode in
attrib/interactive.c and is now also done in non-interactive mode on
patch 03/13.

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

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

* [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface
  2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
                   ` (12 preceding siblings ...)
  2013-03-21 22:31 ` [PATCH 13/13] gatttool: Use error message prefixes consistently Alvaro Silva
@ 2013-04-02 23:31 ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
                     ` (12 more replies)
  13 siblings, 13 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

Hi,

This is the second version of the patches with improvements to
gatttool interactive interface.

As suggested, we rewrote the commit message for patch #03. We also
reordered the patches #02 and #03, so the check for destination
address is removed only after the appropriate check is added to
gatttool.c.

BR,
Alvaro Silva

Alvaro Silva (3):
  gatttool: Show connection state using color
  gatttool: Remove connecting message from prompt
  gatttool: Use error message prefixes consistently

Eder Ruiz Maria (9):
  gatttool: Remote address is mandatory for non-interactive gatttool
  gatttool: Remove check for bluetooth address parameter on
    gatt_connect()
  gatttool: Use GError to propage error messages to caller
  gatttool: Fix issues with printf() and readline prompt
  gatttool: Replace more usages of printf() with rl_printf()
  gatttool: Use bluetoothctl behavior when pressing Enter on empty
    prompt
  gatttool: Use bluetoothctl strategy to handle standard input
  gatttool: Use bluetoothctl strategy for unix signal handling
  gatttool: Show info message when no primary service is found

Jefferson Delfes (1):
  gatttool: Fix memory leak after parsing input line

 Makefile.tools       |    3 +-
 attrib/gatttool.c    |   12 +-
 attrib/gatttool.h    |    3 +-
 attrib/interactive.c |  345 +++++++++++++++++++++++++++++++++-----------------
 attrib/utils.c       |   19 +--
 5 files changed, 249 insertions(+), 133 deletions(-)

-- 
1.7.9.5


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

* [PATCH BlueZ v2 01/13] gatttool: Fix memory leak after parsing input line
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 02/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

The callback is responsible for freeing input line buffer that comes
from rl_callback_handler_install().
---
 attrib/interactive.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index a99ad0a..9f72453 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -850,7 +850,7 @@ static void parse_line(char *line_read)
 	line_read = g_strstrip(line_read);
 
 	if (*line_read == '\0')
-		return;
+		goto done;
 
 	add_history(line_read);
 
@@ -866,6 +866,9 @@ static void parse_line(char *line_read)
 		printf("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
+
+done:
+	free(line_read);
 }
 
 static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
-- 
1.7.9.5


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

* [PATCH BlueZ v2 02/13] gatttool: Remote address is mandatory for non-interactive gatttool
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 03/13] gatttool: Remove check for bluetooth address parameter on gatt_connect() Alvaro Silva
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

For gatttool non-interactive mode, command line parameter with
bluetooth remote address is mandatory.
---
 attrib/gatttool.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 29e3261..1dd0c35 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -603,6 +603,12 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
+	if (opt_dst == NULL) {
+		g_print("Remote Bluetooth address required\n");
+		got_error = TRUE;
+		goto done;
+	}
+
 	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb);
 	if (chan == NULL) {
-- 
1.7.9.5


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

* [PATCH BlueZ v2 03/13] gatttool: Remove check for bluetooth address parameter on gatt_connect()
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 02/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

This check is more appropriate to be done by callers of gatt_connect().
This is already done on interactive mode in attrib/interactive.c and is
now also done in non-interactive mode.
---
 attrib/utils.c |    5 -----
 1 file changed, 5 deletions(-)

diff --git a/attrib/utils.c b/attrib/utils.c
index f9813d1..c8c8651 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -50,11 +50,6 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 	GError *err = NULL;
 	BtIOSecLevel sec;
 
-	/* Remote device */
-	if (dst == NULL) {
-		g_printerr("Remote Bluetooth address required\n");
-		return NULL;
-	}
 	str2ba(dst, &dba);
 
 	/* Local adapter */
-- 
1.7.9.5


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

* [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (2 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 03/13] gatttool: Remove check for bluetooth address parameter on gatt_connect() Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-09 14:26     ` Johan Hedberg
  2013-04-16 15:49     ` [PATCH BlueZ v3] " Eder Ruiz Maria
  2013-04-02 23:31   ` [PATCH BlueZ v2 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
                     ` (8 subsequent siblings)
  12 siblings, 2 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Handle runtime errors outside gatt_connect(), using GError to propagate
error messages to caller.
---
 attrib/gatttool.c    |    6 +++++-
 attrib/gatttool.h    |    3 ++-
 attrib/interactive.c |   10 +++++++---
 attrib/utils.c       |   14 +++++++-------
 4 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1dd0c35..8dbebbb 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -576,6 +576,7 @@ int main(int argc, char *argv[])
 	if (g_option_context_parse(context, &argc, &argv, &gerr) == FALSE) {
 		g_printerr("%s\n", gerr->message);
 		g_error_free(gerr);
+		gerr = NULL;
 	}
 
 	if (opt_interactive) {
@@ -610,8 +611,11 @@ int main(int argc, char *argv[])
 	}
 
 	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb);
+					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
+		g_printerr("%s\n", gerr->message);
+		g_error_free(gerr);
+		gerr = NULL;
 		got_error = TRUE;
 		goto done;
 	}
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 260480d..184a7f8 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -25,5 +25,6 @@ int interactive(const gchar *src, const gchar *dst, const gchar *dst_type,
 								int psm);
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 			const gchar *dst_type, const gchar *sec_level,
-			int psm, int mtu, BtIOConnect connect_cb);
+			int psm, int mtu, BtIOConnect connect_cb,
+			GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9f72453..ce35218 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -395,6 +395,8 @@ static gboolean channel_watcher(GIOChannel *chan, GIOCondition cond,
 
 static void cmd_connect(int argcp, char **argvp)
 {
+	GError *gerr = NULL;
+
 	if (conn_state != STATE_DISCONNECTED)
 		return;
 
@@ -416,10 +418,12 @@ static void cmd_connect(int argcp, char **argvp)
 
 	set_state(STATE_CONNECTING);
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-						opt_psm, opt_mtu, connect_cb);
-	if (iochannel == NULL)
+					opt_psm, opt_mtu, connect_cb, &gerr);
+	if (iochannel == NULL) {
+		printf("%s\n", gerr->message);
 		set_state(STATE_DISCONNECTED);
-	else
+		g_error_free(gerr);
+	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
 }
 
diff --git a/attrib/utils.c b/attrib/utils.c
index c8c8651..e263bcb 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -42,12 +42,13 @@
 
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				const gchar *dst_type, const gchar *sec_level,
-				int psm, int mtu, BtIOConnect connect_cb)
+				int psm, int mtu, BtIOConnect connect_cb,
+				GError **gerr)
 {
 	GIOChannel *chan;
 	bdaddr_t sba, dba;
 	uint8_t dest_type;
-	GError *err = NULL;
+	GError *tmp_err = NULL;
 	BtIOSecLevel sec;
 
 	str2ba(dst, &dba);
@@ -75,7 +76,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 		sec = BT_IO_SEC_LOW;
 
 	if (psm == 0)
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_DEST_TYPE, dest_type,
@@ -83,7 +84,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 	else
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_PSM, psm,
@@ -91,9 +92,8 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 
-	if (err) {
-		g_printerr("%s\n", err->message);
-		g_error_free(err);
+	if (tmp_err) {
+		g_propagate_error(gerr, tmp_err);
 		return NULL;
 	}
 
-- 
1.7.9.5


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

* [PATCH BlueZ v2 05/13] gatttool: Fix issues with printf() and readline prompt
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (3 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Use rl_printf() from bluetoothctl to consistently display messages. This
is specially important for asynchronous callbacks, where using printf()
may mess up the prompt created by readline.
---
 Makefile.tools       |    3 ++-
 attrib/interactive.c |    9 +++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 4d45682..0de0a0d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -189,7 +189,8 @@ noinst_PROGRAMS += attrib/gatttool \
 attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
 				attrib/gattrib.c btio/btio.c \
 				attrib/gatttool.h attrib/interactive.c \
-				attrib/utils.c src/log.c
+				attrib/utils.c src/log.c client/display.c \
+				client/display.h
 attrib_gatttool_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@ -lreadline
 
 tools_obex_client_tool_SOURCES = $(gobex_sources) $(btio_sources) \
diff --git a/attrib/interactive.c b/attrib/interactive.c
index ce35218..d5da9ad 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -40,6 +40,7 @@
 #include "gattrib.h"
 #include "gatt.h"
 #include "gatttool.h"
+#include "client/display.h"
 
 static GIOChannel *iochannel = NULL;
 static GAttrib *attrib = NULL;
@@ -102,7 +103,6 @@ static void set_state(enum state st)
 {
 	conn_state = st;
 	rl_set_prompt(get_prompt());
-	rl_redisplay();
 }
 
 static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
@@ -145,8 +145,8 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	if (err) {
-		printf("connect error: %s\n", err->message);
 		set_state(STATE_DISCONNECTED);
+		rl_printf("%s\n", err->message);
 		return;
 	}
 
@@ -156,6 +156,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
 						events_handler, attrib, NULL);
 	set_state(STATE_CONNECTED);
+	rl_redisplay();
 }
 
 static void disconnect_io()
@@ -412,7 +413,7 @@ static void cmd_connect(int argcp, char **argvp)
 	}
 
 	if (opt_dst == NULL) {
-		printf("Remote Bluetooth address required\n");
+		rl_printf("Remote Bluetooth address required\n");
 		return;
 	}
 
@@ -420,8 +421,8 @@ static void cmd_connect(int argcp, char **argvp)
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
-		printf("%s\n", gerr->message);
 		set_state(STATE_DISCONNECTED);
+		rl_printf("%s\n", gerr->message);
 		g_error_free(gerr);
 	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
-- 
1.7.9.5


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

* [PATCH BlueZ v2 06/13] gatttool: Replace more usages of printf() with rl_printf()
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (4 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

rl_printf() works better with readline than plain printf(), specially on
asynchronous callbacks.
---
 attrib/interactive.c |  177 ++++++++++++++++++++++++--------------------------
 1 file changed, 84 insertions(+), 93 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index d5da9ad..4fd2280 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -110,27 +110,31 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 	uint8_t *opdu;
 	uint16_t handle, i, olen;
 	size_t plen;
+	GString *s;
 
 	handle = att_get_u16(&pdu[1]);
 
-	printf("\n");
 	switch (pdu[0]) {
 	case ATT_OP_HANDLE_NOTIFY:
-		printf("Notification handle = 0x%04x value: ", handle);
+		s = g_string_new(NULL);
+		g_string_printf(s, "Notification handle = 0x%04x value: ",
+									handle);
 		break;
 	case ATT_OP_HANDLE_IND:
-		printf("Indication   handle = 0x%04x value: ", handle);
+		s = g_string_new(NULL);
+		g_string_printf(s, "Indication   handle = 0x%04x value: ",
+									handle);
 		break;
 	default:
-		printf("Invalid opcode\n");
+		rl_printf("Invalid opcode\n");
 		return;
 	}
 
 	for (i = 3; i < len; i++)
-		printf("%02x ", pdu[i]);
+		g_string_append_printf(s, "%02x ", pdu[i]);
 
-	printf("\n");
-	rl_forced_update_display();
+	rl_printf("%s\n", s->str);
+	g_string_free(s, TRUE);
 
 	if (pdu[0] == ATT_OP_HANDLE_NOTIFY)
 		return;
@@ -180,19 +184,16 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Discover all primary services failed: %s\n",
+		rl_printf("Discover all primary services failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = services; l; l = l->next) {
 		struct gatt_primary *prim = l->data;
-		printf("attr handle: 0x%04x, end grp handle: 0x%04x "
-			"uuid: %s\n", prim->range.start, prim->range.end, prim->uuid);
+		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
+				prim->range.start, prim->range.end, prim->uuid);
 	}
-
-	rl_forced_update_display();
 }
 
 static void primary_by_uuid_cb(GSList *ranges, guint8 status,
@@ -201,19 +202,16 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 	GSList *l;
 
 	if (status) {
-		printf("Discover primary services by UUID failed: %s\n",
+		rl_printf("Discover primary services by UUID failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = ranges; l; l = l->next) {
 		struct att_range *range = l->data;
-		g_print("Starting handle: 0x%04x Ending handle: 0x%04x\n",
+		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
 						range->start, range->end);
 	}
-
-	rl_forced_update_display();
 }
 
 static void included_cb(GSList *includes, guint8 status, gpointer user_data)
@@ -221,27 +219,23 @@ static void included_cb(GSList *includes, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Find included services failed: %s\n",
+		rl_printf("Find included services failed: %s\n",
 							att_ecode2str(status));
-		goto done;
+		return;
 	}
 
 	if (includes == NULL) {
-		printf("No included services found for this range\n");
-		goto done;
+		rl_printf("No included services found for this range\n");
+		return;
 	}
 
-	printf("\n");
 	for (l = includes; l; l = l->next) {
 		struct gatt_included *incl = l->data;
-		printf("handle: 0x%04x, start handle: 0x%04x, "
+		rl_printf("handle: 0x%04x, start handle: 0x%04x, "
 					"end handle: 0x%04x uuid: %s\n",
 					incl->handle, incl->range.start,
 					incl->range.end, incl->uuid);
 	}
-
-done:
-	rl_forced_update_display();
 }
 
 static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
@@ -249,22 +243,19 @@ static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		printf("Discover all characteristics failed: %s\n",
+		rl_printf("Discover all characteristics failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
-	printf("\n");
 	for (l = characteristics; l; l = l->next) {
 		struct gatt_char *chars = l->data;
 
-		printf("handle: 0x%04x, char properties: 0x%02x, char value "
+		rl_printf("handle: 0x%04x, char properties: 0x%02x, char value "
 				"handle: 0x%04x, uuid: %s\n", chars->handle,
 				chars->properties, chars->value_handle,
 				chars->uuid);
 	}
-
-	rl_forced_update_display();
 }
 
 static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -276,7 +267,7 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	int i;
 
 	if (status != 0) {
-		printf("Discover descriptors finished: %s\n",
+		rl_printf("Discover descriptors finished: %s\n",
 						att_ecode2str(status));
 		return;
 	}
@@ -285,7 +276,6 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	if (list == NULL)
 		return;
 
-	printf("\n");
 	for (i = 0; i < list->num; i++) {
 		char uuidstr[MAX_LEN_UUID_STR];
 		uint8_t *value;
@@ -300,15 +290,13 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
 			uuid = att_get_uuid128(&value[2]);
 
 		bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
-		printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
+		rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
 	}
 
 	att_data_list_free(list);
 
 	if (handle != 0xffff && handle < end)
 		gatt_find_info(attrib, handle + 1, end, char_desc_cb, NULL);
-	else
-		rl_forced_update_display();
 }
 
 static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -317,25 +305,26 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint8_t value[plen];
 	ssize_t vlen;
 	int i;
+	GString *s;
 
 	if (status != 0) {
-		printf("Characteristic value/descriptor read failed: %s\n",
+		rl_printf("Characteristic value/descriptor read failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
 	if (vlen < 0) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
-	printf("\nCharacteristic value/descriptor: ");
+	s = g_string_new("Characteristic value/descriptor: ");
 	for (i = 0; i < vlen; i++)
-		printf("%02x ", value[i]);
-	printf("\n");
+		g_string_append_printf(s, "%02x ", value[i]);
 
-	rl_forced_update_display();
+	rl_printf("%s\n", s->str);
+	g_string_free(s, TRUE);
 }
 
 static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
@@ -344,13 +333,14 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 	struct characteristic_data *char_data = user_data;
 	struct att_data_list *list;
 	int i;
+	GString *s;
 
 	if (status == ATT_ECODE_ATTR_NOT_FOUND &&
 				char_data->start != char_data->orig_start)
 		goto done;
 
 	if (status != 0) {
-		printf("Read characteristics by UUID failed: %s\n",
+		rl_printf("Read characteristics by UUID failed: %s\n",
 							att_ecode2str(status));
 		goto done;
 	}
@@ -359,22 +349,23 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 	if (list == NULL)
 		goto done;
 
+	s = g_string_new(NULL);
 	for (i = 0; i < list->num; i++) {
 		uint8_t *value = list->data[i];
 		int j;
 
 		char_data->start = att_get_u16(value) + 1;
-
-		printf("\nhandle: 0x%04x \t value: ", att_get_u16(value));
+		g_string_printf(s, "handle: 0x%04x \t value: ",
+							att_get_u16(value));
 		value += 2;
 		for (j = 0; j < list->len - 2; j++, value++)
-			printf("%02x ", *value);
-		printf("\n");
+			g_string_append_printf(s, "%02x ", *value);
+
+		rl_printf("%s\n", s->str);
 	}
 
 	att_data_list_free(list);
-
-	rl_forced_update_display();
+	g_string_free(s, TRUE);
 
 done:
 	g_free(char_data);
@@ -438,7 +429,7 @@ static void cmd_primary(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
@@ -448,7 +439,7 @@ static void cmd_primary(int argcp, char **argvp)
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		printf("Invalid UUID\n");
+		rl_printf("Invalid UUID\n");
 		return;
 	}
 
@@ -474,14 +465,14 @@ static void cmd_included(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 		end = start;
@@ -490,7 +481,7 @@ static void cmd_included(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -504,14 +495,14 @@ static void cmd_char(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -519,7 +510,7 @@ static void cmd_char(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -528,7 +519,7 @@ static void cmd_char(int argcp, char **argvp)
 		bt_uuid_t uuid;
 
 		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
-			printf("Invalid UUID\n");
+			rl_printf("Invalid UUID\n");
 			return;
 		}
 
@@ -542,14 +533,14 @@ static void cmd_char(int argcp, char **argvp)
 static void cmd_char_desc(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	} else
@@ -558,7 +549,7 @@ static void cmd_char_desc(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	} else
@@ -572,18 +563,18 @@ static void cmd_read_hnd(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Missing argument: handle\n");
+		rl_printf("Missing argument: handle\n");
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle < 0) {
-		printf("Invalid handle: %s\n", argvp[1]);
+		rl_printf("Invalid handle: %s\n", argvp[1]);
 		return;
 	}
 
@@ -598,24 +589,24 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Missing argument: UUID\n");
+		rl_printf("Missing argument: UUID\n");
 		return;
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		printf("Invalid UUID\n");
+		rl_printf("Invalid UUID\n");
 		return;
 	}
 
 	if (argcp > 2) {
 		start = strtohandle(argvp[2]);
 		if (start < 0) {
-			printf("Invalid start handle: %s\n", argvp[1]);
+			rl_printf("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -623,7 +614,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	if (argcp > 3) {
 		end = strtohandle(argvp[3]);
 		if (end < 0) {
-			printf("Invalid end handle: %s\n", argvp[2]);
+			rl_printf("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -642,17 +633,17 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
 	if (status != 0) {
-		printf("Characteristic Write Request failed: "
+		rl_printf("Characteristic Write Request failed: "
 						"%s\n", att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
-	printf("Characteristic value was written successfully\n");
+	rl_printf("Characteristic value was written successfully\n");
 }
 
 static void cmd_char_write(int argcp, char **argvp)
@@ -662,24 +653,24 @@ static void cmd_char_write(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: disconnected\n");
+		rl_printf("Command failed: disconnected\n");
 		return;
 	}
 
 	if (argcp < 3) {
-		printf("Usage: %s <handle> <new value>\n", argvp[0]);
+		rl_printf("Usage: %s <handle> <new value>\n", argvp[0]);
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle <= 0) {
-		printf("A valid handle is required\n");
+		rl_printf("A valid handle is required\n");
 		return;
 	}
 
 	plen = gatt_attr_data_from_string(argvp[2], &value);
 	if (plen == 0) {
-		g_printerr("Invalid value\n");
+		rl_printf("Invalid value\n");
 		return;
 	}
 
@@ -698,7 +689,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 	BtIOSecLevel sec_level;
 
 	if (argcp < 2) {
-		printf("sec-level: %s\n", opt_sec_level);
+		rl_printf("sec-level: %s\n", opt_sec_level);
 		return;
 	}
 
@@ -709,7 +700,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 	else if (strcasecmp(argvp[1], "low") == 0)
 		sec_level = BT_IO_SEC_LOW;
 	else {
-		printf("Allowed values: low | medium | high\n");
+		rl_printf("Allowed values: low | medium | high\n");
 		return;
 	}
 
@@ -720,7 +711,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 		return;
 
 	if (opt_psm) {
-		printf("It must be reconnected to this change take effect\n");
+		rl_printf("Change will take effect on reconnection\n");
 		return;
 	}
 
@@ -728,7 +719,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 			BT_IO_OPT_SEC_LEVEL, sec_level,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
-		printf("Error: %s\n", gerr->message);
+		rl_printf("Error: %s\n", gerr->message);
 		g_error_free(gerr);
 	}
 }
@@ -739,44 +730,44 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint16_t mtu;
 
 	if (status != 0) {
-		printf("Exchange MTU Request failed: %s\n",
+		rl_printf("Exchange MTU Request failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_mtu_resp(pdu, plen, &mtu)) {
-		printf("Protocol error\n");
+		rl_printf("Protocol error\n");
 		return;
 	}
 
 	mtu = MIN(mtu, opt_mtu);
 	/* Set new value for MTU in client */
 	if (g_attrib_set_mtu(attrib, mtu))
-		printf("MTU was exchanged successfully: %d\n", mtu);
+		rl_printf("MTU was exchanged successfully: %d\n", mtu);
 	else
-		printf("Error exchanging MTU\n");
+		rl_printf("Error exchanging MTU\n");
 }
 
 static void cmd_mtu(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		printf("Command failed: not connected.\n");
+		rl_printf("Command failed: not connected.\n");
 		return;
 	}
 
 	if (opt_psm) {
-		printf("Command failed: operation is only available for LE"
+		rl_printf("Command failed: operation is only available for LE"
 							" transport.\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		printf("Usage: mtu <value>\n");
+		rl_printf("Usage: mtu <value>\n");
 		return;
 	}
 
 	if (opt_mtu) {
-		printf("Command failed: MTU exchange can only occur once per"
+		rl_printf("Command failed: MTU exchange can only occur once per"
 							" connection.\n");
 		return;
 	}
@@ -784,7 +775,7 @@ static void cmd_mtu(int argcp, char **argvp)
 	errno = 0;
 	opt_mtu = strtoll(argvp[1], NULL, 0);
 	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
-		printf("Invalid value. Minimum MTU size is %d\n",
+		rl_printf("Invalid value. Minimum MTU size is %d\n",
 							ATT_DEFAULT_LE_MTU);
 		return;
 	}
@@ -836,7 +827,7 @@ static void cmd_help(int argcp, char **argvp)
 	int i;
 
 	for (i = 0; commands[i].cmd; i++)
-		printf("%-15s %-30s %s\n", commands[i].cmd,
+		rl_printf("%-15s %-30s %s\n", commands[i].cmd,
 				commands[i].params, commands[i].desc);
 }
 
@@ -847,7 +838,7 @@ static void parse_line(char *line_read)
 	int i;
 
 	if (line_read == NULL) {
-		printf("\n");
+		rl_printf("\n");
 		cmd_exit(0, NULL);
 		return;
 	}
@@ -868,7 +859,7 @@ static void parse_line(char *line_read)
 	if (commands[i].cmd)
 		commands[i].func(argcp, argvp);
 	else
-		printf("%s: command not found\n", argvp[0]);
+		rl_printf("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
 
-- 
1.7.9.5


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

* [PATCH BlueZ v2 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (5 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 08/13] gatttool: Show connection state using color Alvaro Silva
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

---
 attrib/interactive.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 4fd2280..ecb8b7d 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -930,6 +930,7 @@ int interactive(const gchar *src, const gchar *dst,
 	g_io_add_watch(pchan, events, prompt_read, NULL);
 
 	rl_attempted_completion_function = commands_completion;
+	rl_erase_empty_line = 1;
 	rl_callback_handler_install(get_prompt(), parse_line);
 
 	g_main_loop_run(event_loop);
-- 
1.7.9.5


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

* [PATCH BlueZ v2 08/13] gatttool: Show connection state using color
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (6 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

When device is connected, the Bluetooth address is shown in blue color.
---
 attrib/interactive.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index ecb8b7d..5ffe2fb 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -79,15 +79,15 @@ static char *get_prompt(void)
 	}
 
 	if (conn_state == STATE_CONNECTED)
-		g_string_assign(prompt, "[CON]");
-	else
-		g_string_assign(prompt, "[   ]");
+		g_string_append(prompt, COLOR_BLUE);
 
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
 		g_string_append_printf(prompt, "[%17s]", "");
 
+	g_string_append(prompt, COLOR_OFF);
+
 	if (opt_psm)
 		g_string_append(prompt, "[BR]");
 	else
-- 
1.7.9.5


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

* [PATCH BlueZ v2 09/13] gatttool: Remove connecting message from prompt
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (7 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 08/13] gatttool: Show connection state using color Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

When trying to connect, the "connecting" message is not set as prompt
anymore. Instead, it is printed just like other status messages and the
prompt is kept, allowing the user to send commands while connection is
being established.
---
 attrib/interactive.c |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 5ffe2fb..7520324 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -73,20 +73,18 @@ static enum state {
 
 static char *get_prompt(void)
 {
-	if (conn_state == STATE_CONNECTING) {
-		g_string_assign(prompt, "Connecting... ");
-		return prompt->str;
-	}
-
 	if (conn_state == STATE_CONNECTED)
-		g_string_append(prompt, COLOR_BLUE);
+		g_string_assign(prompt, COLOR_BLUE);
+	else
+		g_string_assign(prompt, "");
 
 	if (opt_dst)
 		g_string_append_printf(prompt, "[%17s]", opt_dst);
 	else
 		g_string_append_printf(prompt, "[%17s]", "");
 
-	g_string_append(prompt, COLOR_OFF);
+	if (conn_state == STATE_CONNECTED)
+		g_string_append(prompt, COLOR_OFF);
 
 	if (opt_psm)
 		g_string_append(prompt, "[BR]");
@@ -160,7 +158,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
 						events_handler, attrib, NULL);
 	set_state(STATE_CONNECTED);
-	rl_redisplay();
+	rl_printf("Connection successful\n");
 }
 
 static void disconnect_io()
@@ -408,6 +406,7 @@ static void cmd_connect(int argcp, char **argvp)
 		return;
 	}
 
+	rl_printf("Attempting to connect to %s\n", opt_dst);
 	set_state(STATE_CONNECTING);
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
 					opt_psm, opt_mtu, connect_cb, &gerr);
-- 
1.7.9.5


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

* [PATCH BlueZ v2 10/13] gatttool: Use bluetoothctl strategy to handle standard input
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (8 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Use GSource id returned by g_io_add_watch() instead of raw GIOChannel to
handle stdin and glib main loop.
---
 attrib/interactive.c |   26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 7520324..fa3f82a 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -906,11 +906,26 @@ static char **commands_completion(const char *text, int start, int end)
 		return NULL;
 }
 
+static guint setup_standard_input(void)
+{
+	GIOChannel *channel;
+	guint source;
+
+	channel = g_io_channel_unix_new(fileno(stdin));
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				prompt_read, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int interactive(const gchar *src, const gchar *dst,
 		const gchar *dst_type, int psm)
 {
-	GIOChannel *pchan;
-	gint events;
+	guint input;
 
 	opt_sec_level = g_strdup("low");
 
@@ -923,10 +938,7 @@ int interactive(const gchar *src, const gchar *dst,
 
 	event_loop = g_main_loop_new(NULL, FALSE);
 
-	pchan = g_io_channel_unix_new(fileno(stdin));
-	g_io_channel_set_close_on_unref(pchan, TRUE);
-	events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-	g_io_add_watch(pchan, events, prompt_read, NULL);
+	input = setup_standard_input();
 
 	rl_attempted_completion_function = commands_completion;
 	rl_erase_empty_line = 1;
@@ -936,7 +948,7 @@ int interactive(const gchar *src, const gchar *dst,
 
 	rl_callback_handler_remove();
 	cmd_disconnect(0, NULL);
-	g_io_channel_unref(pchan);
+	g_source_remove(input);
 	g_main_loop_unref(event_loop);
 	g_string_free(prompt, TRUE);
 
-- 
1.7.9.5


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

* [PATCH BlueZ v2 11/13] gatttool: Use bluetoothctl strategy for unix signal handling
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (9 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 13/13] gatttool: Use error message prefixes consistently Alvaro Silva
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

Now to exit from gatttool at interactive mode, user must use SIGTERM(15)
or press Ctrl+D. SIGINT(2) or Ctrl+C just flushes typed characters and
breaks line.
---
 attrib/interactive.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index fa3f82a..9b16ddf 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -29,6 +29,9 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/signalfd.h>
 #include <glib.h>
 
 #include <readline/readline.h>
@@ -922,10 +925,88 @@ static guint setup_standard_input(void)
 	return source;
 }
 
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+							gpointer user_data)
+{
+	static unsigned int __terminated = 0;
+	struct signalfd_siginfo si;
+	ssize_t result;
+	int fd;
+
+	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		g_main_loop_quit(event_loop);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	result = read(fd, &si, sizeof(si));
+	if (result != sizeof(si))
+		return FALSE;
+
+	switch (si.ssi_signo) {
+	case SIGINT:
+		rl_replace_line("", 0);
+		rl_crlf();
+		rl_on_new_line();
+		rl_redisplay();
+		break;
+	case SIGTERM:
+		if (__terminated == 0) {
+			rl_replace_line("", 0);
+			rl_crlf();
+			g_main_loop_quit(event_loop);
+		}
+
+		__terminated = 1;
+		break;
+	}
+
+	return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+	GIOChannel *channel;
+	guint source;
+	sigset_t mask;
+	int fd;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+		perror("Failed to set signal mask");
+		return 0;
+	}
+
+	fd = signalfd(-1, &mask, 0);
+	if (fd < 0) {
+		perror("Failed to create signal descriptor");
+		return 0;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				signal_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return source;
+}
+
 int interactive(const gchar *src, const gchar *dst,
 		const gchar *dst_type, int psm)
 {
 	guint input;
+	guint signal;
 
 	opt_sec_level = g_strdup("low");
 
@@ -939,6 +1020,7 @@ int interactive(const gchar *src, const gchar *dst,
 	event_loop = g_main_loop_new(NULL, FALSE);
 
 	input = setup_standard_input();
+	signal = setup_signalfd();
 
 	rl_attempted_completion_function = commands_completion;
 	rl_erase_empty_line = 1;
@@ -949,6 +1031,7 @@ int interactive(const gchar *src, const gchar *dst,
 	rl_callback_handler_remove();
 	cmd_disconnect(0, NULL);
 	g_source_remove(input);
+	g_source_remove(signal);
 	g_main_loop_unref(event_loop);
 	g_string_free(prompt, TRUE);
 
-- 
1.7.9.5


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

* [PATCH BlueZ v2 12/13] gatttool: Show info message when no primary service is found
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (10 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  2013-04-02 23:31   ` [PATCH BlueZ v2 13/13] gatttool: Use error message prefixes consistently Alvaro Silva
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

From: Eder Ruiz Maria <eder.ruiz@openbossa.org>

---
 attrib/interactive.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9b16ddf..1d31889 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -190,6 +190,11 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 		return;
 	}
 
+	if (services == NULL) {
+		rl_printf("No primary service found\n");
+		return;
+	}
+
 	for (l = services; l; l = l->next) {
 		struct gatt_primary *prim = l->data;
 		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
@@ -208,6 +213,11 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 		return;
 	}
 
+	if (ranges == NULL) {
+		rl_printf("No service UUID found\n");
+		return;
+	}
+
 	for (l = ranges; l; l = l->next) {
 		struct att_range *range = l->data;
 		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
-- 
1.7.9.5


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

* [PATCH BlueZ v2 13/13] gatttool: Use error message prefixes consistently
  2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
                     ` (11 preceding siblings ...)
  2013-04-02 23:31   ` [PATCH BlueZ v2 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
@ 2013-04-02 23:31   ` Alvaro Silva
  12 siblings, 0 replies; 32+ messages in thread
From: Alvaro Silva @ 2013-04-02 23:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Alvaro Silva

Replace rl_printf() calls with macros that add appropriate prefixes.
---
 attrib/interactive.c |  107 ++++++++++++++++++++++++++------------------------
 1 file changed, 56 insertions(+), 51 deletions(-)

diff --git a/attrib/interactive.c b/attrib/interactive.c
index 1d31889..a819acf 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -27,6 +27,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -74,6 +75,12 @@ static enum state {
 	STATE_CONNECTED
 } conn_state;
 
+#define error(fmt, arg...) \
+	rl_printf(COLOR_RED "Error: " COLOR_OFF fmt, ## arg)
+
+#define failed(fmt, arg...) \
+	rl_printf(COLOR_RED "Command Failed: " COLOR_OFF fmt, ## arg)
+
 static char *get_prompt(void)
 {
 	if (conn_state == STATE_CONNECTED)
@@ -127,7 +134,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
 									handle);
 		break;
 	default:
-		rl_printf("Invalid opcode\n");
+		error("Invalid opcode\n");
 		return;
 	}
 
@@ -151,7 +158,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	if (err) {
 		set_state(STATE_DISCONNECTED);
-		rl_printf("%s\n", err->message);
+		error("%s\n", err->message);
 		return;
 	}
 
@@ -185,13 +192,13 @@ static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover all primary services failed: %s\n",
-							att_ecode2str(status));
+		error("Discover all primary services failed: %s\n",
+						att_ecode2str(status));
 		return;
 	}
 
 	if (services == NULL) {
-		rl_printf("No primary service found\n");
+		error("No primary service found\n");
 		return;
 	}
 
@@ -208,13 +215,13 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover primary services by UUID failed: %s\n",
+		error("Discover primary services by UUID failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	if (ranges == NULL) {
-		rl_printf("No service UUID found\n");
+		error("No service UUID found\n");
 		return;
 	}
 
@@ -230,7 +237,7 @@ static void included_cb(GSList *includes, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Find included services failed: %s\n",
+		error("Find included services failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
@@ -254,7 +261,7 @@ static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
 	GSList *l;
 
 	if (status) {
-		rl_printf("Discover all characteristics failed: %s\n",
+		error("Discover all characteristics failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
@@ -319,14 +326,14 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	GString *s;
 
 	if (status != 0) {
-		rl_printf("Characteristic value/descriptor read failed: %s\n",
+		error("Characteristic value/descriptor read failed: %s\n",
 							att_ecode2str(status));
 		return;
 	}
 
 	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
 	if (vlen < 0) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -351,7 +358,7 @@ static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
 		goto done;
 
 	if (status != 0) {
-		rl_printf("Read characteristics by UUID failed: %s\n",
+		error("Read characteristics by UUID failed: %s\n",
 							att_ecode2str(status));
 		goto done;
 	}
@@ -415,7 +422,7 @@ static void cmd_connect(int argcp, char **argvp)
 	}
 
 	if (opt_dst == NULL) {
-		rl_printf("Remote Bluetooth address required\n");
+		error("Remote Bluetooth address required\n");
 		return;
 	}
 
@@ -425,7 +432,7 @@ static void cmd_connect(int argcp, char **argvp)
 					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (iochannel == NULL) {
 		set_state(STATE_DISCONNECTED);
-		rl_printf("%s\n", gerr->message);
+		error("%s\n", gerr->message);
 		g_error_free(gerr);
 	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
@@ -441,7 +448,7 @@ static void cmd_primary(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
@@ -451,7 +458,7 @@ static void cmd_primary(int argcp, char **argvp)
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		rl_printf("Invalid UUID\n");
+		error("Invalid UUID\n");
 		return;
 	}
 
@@ -477,14 +484,14 @@ static void cmd_included(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 		end = start;
@@ -493,7 +500,7 @@ static void cmd_included(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -507,14 +514,14 @@ static void cmd_char(int argcp, char **argvp)
 	int end = 0xffff;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -522,7 +529,7 @@ static void cmd_char(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -531,7 +538,7 @@ static void cmd_char(int argcp, char **argvp)
 		bt_uuid_t uuid;
 
 		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
-			rl_printf("Invalid UUID\n");
+			error("Invalid UUID\n");
 			return;
 		}
 
@@ -545,14 +552,14 @@ static void cmd_char(int argcp, char **argvp)
 static void cmd_char_desc(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp > 1) {
 		start = strtohandle(argvp[1]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	} else
@@ -561,7 +568,7 @@ static void cmd_char_desc(int argcp, char **argvp)
 	if (argcp > 2) {
 		end = strtohandle(argvp[2]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	} else
@@ -575,18 +582,18 @@ static void cmd_read_hnd(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		rl_printf("Missing argument: handle\n");
+		error("Missing argument: handle\n");
 		return;
 	}
 
 	handle = strtohandle(argvp[1]);
 	if (handle < 0) {
-		rl_printf("Invalid handle: %s\n", argvp[1]);
+		error("Invalid handle: %s\n", argvp[1]);
 		return;
 	}
 
@@ -601,24 +608,24 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	bt_uuid_t uuid;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (argcp < 2) {
-		rl_printf("Missing argument: UUID\n");
+		error("Missing argument: UUID\n");
 		return;
 	}
 
 	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
-		rl_printf("Invalid UUID\n");
+		error("Invalid UUID\n");
 		return;
 	}
 
 	if (argcp > 2) {
 		start = strtohandle(argvp[2]);
 		if (start < 0) {
-			rl_printf("Invalid start handle: %s\n", argvp[1]);
+			error("Invalid start handle: %s\n", argvp[1]);
 			return;
 		}
 	}
@@ -626,7 +633,7 @@ static void cmd_read_uuid(int argcp, char **argvp)
 	if (argcp > 3) {
 		end = strtohandle(argvp[3]);
 		if (end < 0) {
-			rl_printf("Invalid end handle: %s\n", argvp[2]);
+			error("Invalid end handle: %s\n", argvp[2]);
 			return;
 		}
 	}
@@ -645,13 +652,13 @@ static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
 							gpointer user_data)
 {
 	if (status != 0) {
-		rl_printf("Characteristic Write Request failed: "
+		error("Characteristic Write Request failed: "
 						"%s\n", att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -665,7 +672,7 @@ static void cmd_char_write(int argcp, char **argvp)
 	int handle;
 
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: disconnected\n");
+		failed("Disconnected\n");
 		return;
 	}
 
@@ -676,13 +683,13 @@ static void cmd_char_write(int argcp, char **argvp)
 
 	handle = strtohandle(argvp[1]);
 	if (handle <= 0) {
-		rl_printf("A valid handle is required\n");
+		error("A valid handle is required\n");
 		return;
 	}
 
 	plen = gatt_attr_data_from_string(argvp[2], &value);
 	if (plen == 0) {
-		rl_printf("Invalid value\n");
+		error("Invalid value\n");
 		return;
 	}
 
@@ -731,7 +738,7 @@ static void cmd_sec_level(int argcp, char **argvp)
 			BT_IO_OPT_SEC_LEVEL, sec_level,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
-		rl_printf("Error: %s\n", gerr->message);
+		error("%s\n", gerr->message);
 		g_error_free(gerr);
 	}
 }
@@ -742,13 +749,13 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	uint16_t mtu;
 
 	if (status != 0) {
-		rl_printf("Exchange MTU Request failed: %s\n",
-							att_ecode2str(status));
+		error("Exchange MTU Request failed: %s\n",
+						att_ecode2str(status));
 		return;
 	}
 
 	if (!dec_mtu_resp(pdu, plen, &mtu)) {
-		rl_printf("Protocol error\n");
+		error("Protocol error\n");
 		return;
 	}
 
@@ -757,19 +764,18 @@ static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	if (g_attrib_set_mtu(attrib, mtu))
 		rl_printf("MTU was exchanged successfully: %d\n", mtu);
 	else
-		rl_printf("Error exchanging MTU\n");
+		error("Error exchanging MTU\n");
 }
 
 static void cmd_mtu(int argcp, char **argvp)
 {
 	if (conn_state != STATE_CONNECTED) {
-		rl_printf("Command failed: not connected.\n");
+		failed("Disconnected\n");
 		return;
 	}
 
 	if (opt_psm) {
-		rl_printf("Command failed: operation is only available for LE"
-							" transport.\n");
+		failed("Operation is only available for LE transport.\n");
 		return;
 	}
 
@@ -779,15 +785,14 @@ static void cmd_mtu(int argcp, char **argvp)
 	}
 
 	if (opt_mtu) {
-		rl_printf("Command failed: MTU exchange can only occur once per"
-							" connection.\n");
+		failed("MTU exchange can only occur once per connection.\n");
 		return;
 	}
 
 	errno = 0;
 	opt_mtu = strtoll(argvp[1], NULL, 0);
 	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
-		rl_printf("Invalid value. Minimum MTU size is %d\n",
+		error("Invalid value. Minimum MTU size is %d\n",
 							ATT_DEFAULT_LE_MTU);
 		return;
 	}
@@ -871,7 +876,7 @@ static void parse_line(char *line_read)
 	if (commands[i].cmd)
 		commands[i].func(argcp, argvp);
 	else
-		rl_printf("%s: command not found\n", argvp[0]);
+		error("%s: command not found\n", argvp[0]);
 
 	g_strfreev(argvp);
 
-- 
1.7.9.5


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

* Re: [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller
  2013-04-02 23:31   ` [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
@ 2013-04-09 14:26     ` Johan Hedberg
  2013-04-16 15:49     ` [PATCH BlueZ v3] " Eder Ruiz Maria
  1 sibling, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-04-09 14:26 UTC (permalink / raw)
  To: Alvaro Silva; +Cc: linux-bluetooth, Eder Ruiz Maria

Hi,

On Tue, Apr 02, 2013, Alvaro Silva wrote:
> Handle runtime errors outside gatt_connect(), using GError to propagate
> error messages to caller.
> ---
>  attrib/gatttool.c    |    6 +++++-
>  attrib/gatttool.h    |    3 ++-
>  attrib/interactive.c |   10 +++++++---
>  attrib/utils.c       |   14 +++++++-------
>  4 files changed, 21 insertions(+), 12 deletions(-)

The first three patches have been applied, but there are a few issues
with this one:

> --- a/attrib/gatttool.c
> +++ b/attrib/gatttool.c
> @@ -576,6 +576,7 @@ int main(int argc, char *argv[])
>  	if (g_option_context_parse(context, &argc, &argv, &gerr) == FALSE) {
>  		g_printerr("%s\n", gerr->message);
>  		g_error_free(gerr);
> +		gerr = NULL;

g_error_free + gerr = NULL is the same as g_clear_error(&gerr). Please
use that instead.

>  	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
> -					opt_psm, opt_mtu, connect_cb);
> +					opt_psm, opt_mtu, connect_cb, &gerr);
>  	if (chan == NULL) {
> +		g_printerr("%s\n", gerr->message);
> +		g_error_free(gerr);
> +		gerr = NULL;

Same here.

Johan

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

* [PATCH BlueZ v3] gatttool: Use GError to propage error messages to caller
  2013-04-02 23:31   ` [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
  2013-04-09 14:26     ` Johan Hedberg
@ 2013-04-16 15:49     ` Eder Ruiz Maria
  2013-04-17  8:24       ` Johan Hedberg
  1 sibling, 1 reply; 32+ messages in thread
From: Eder Ruiz Maria @ 2013-04-16 15:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eder Ruiz Maria

Handle runtime errors outside gatt_connect(), using GError to propagate
error messages to caller.
---
 attrib/gatttool.c    |    6 ++++--
 attrib/gatttool.h    |    3 ++-
 attrib/interactive.c |   10 +++++++---
 attrib/utils.c       |   14 +++++++-------
 4 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1dd0c35..e1d8407 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -575,7 +575,7 @@ int main(int argc, char *argv[])
 
 	if (g_option_context_parse(context, &argc, &argv, &gerr) == FALSE) {
 		g_printerr("%s\n", gerr->message);
-		g_error_free(gerr);
+		g_clear_error(&gerr);
 	}
 
 	if (opt_interactive) {
@@ -610,8 +610,10 @@ int main(int argc, char *argv[])
 	}
 
 	chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-					opt_psm, opt_mtu, connect_cb);
+					opt_psm, opt_mtu, connect_cb, &gerr);
 	if (chan == NULL) {
+		g_printerr("%s\n", gerr->message);
+		g_clear_error(&gerr);
 		got_error = TRUE;
 		goto done;
 	}
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 260480d..184a7f8 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -25,5 +25,6 @@ int interactive(const gchar *src, const gchar *dst, const gchar *dst_type,
 								int psm);
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 			const gchar *dst_type, const gchar *sec_level,
-			int psm, int mtu, BtIOConnect connect_cb);
+			int psm, int mtu, BtIOConnect connect_cb,
+			GError **gerr);
 size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9f72453..ce35218 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -395,6 +395,8 @@ static gboolean channel_watcher(GIOChannel *chan, GIOCondition cond,
 
 static void cmd_connect(int argcp, char **argvp)
 {
+	GError *gerr = NULL;
+
 	if (conn_state != STATE_DISCONNECTED)
 		return;
 
@@ -416,10 +418,12 @@ static void cmd_connect(int argcp, char **argvp)
 
 	set_state(STATE_CONNECTING);
 	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
-						opt_psm, opt_mtu, connect_cb);
-	if (iochannel == NULL)
+					opt_psm, opt_mtu, connect_cb, &gerr);
+	if (iochannel == NULL) {
+		printf("%s\n", gerr->message);
 		set_state(STATE_DISCONNECTED);
-	else
+		g_error_free(gerr);
+	} else
 		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
 }
 
diff --git a/attrib/utils.c b/attrib/utils.c
index c8c8651..e263bcb 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -42,12 +42,13 @@
 
 GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				const gchar *dst_type, const gchar *sec_level,
-				int psm, int mtu, BtIOConnect connect_cb)
+				int psm, int mtu, BtIOConnect connect_cb,
+				GError **gerr)
 {
 	GIOChannel *chan;
 	bdaddr_t sba, dba;
 	uint8_t dest_type;
-	GError *err = NULL;
+	GError *tmp_err = NULL;
 	BtIOSecLevel sec;
 
 	str2ba(dst, &dba);
@@ -75,7 +76,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 		sec = BT_IO_SEC_LOW;
 
 	if (psm == 0)
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_DEST_TYPE, dest_type,
@@ -83,7 +84,7 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 	else
-		chan = bt_io_connect(connect_cb, NULL, NULL, &err,
+		chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err,
 				BT_IO_OPT_SOURCE_BDADDR, &sba,
 				BT_IO_OPT_DEST_BDADDR, &dba,
 				BT_IO_OPT_PSM, psm,
@@ -91,9 +92,8 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
 				BT_IO_OPT_SEC_LEVEL, sec,
 				BT_IO_OPT_INVALID);
 
-	if (err) {
-		g_printerr("%s\n", err->message);
-		g_error_free(err);
+	if (tmp_err) {
+		g_propagate_error(gerr, tmp_err);
 		return NULL;
 	}
 
-- 
1.7.10.4


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

* Re: [PATCH BlueZ v3] gatttool: Use GError to propage error messages to caller
  2013-04-16 15:49     ` [PATCH BlueZ v3] " Eder Ruiz Maria
@ 2013-04-17  8:24       ` Johan Hedberg
  0 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-04-17  8:24 UTC (permalink / raw)
  To: Eder Ruiz Maria; +Cc: linux-bluetooth

Hi Eder,

On Tue, Apr 16, 2013, Eder Ruiz Maria wrote:
> Handle runtime errors outside gatt_connect(), using GError to propagate
> error messages to caller.
> ---
>  attrib/gatttool.c    |    6 ++++--
>  attrib/gatttool.h    |    3 ++-
>  attrib/interactive.c |   10 +++++++---
>  attrib/utils.c       |   14 +++++++-------
>  4 files changed, 20 insertions(+), 13 deletions(-)

Thanks. This as well as the rest of the patches in the set have now been
applied.

Johan

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

end of thread, other threads:[~2013-04-17  8:24 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-21 22:31 [PATCH 00/13] Improvements on gatttool interactive interface Alvaro Silva
2013-03-21 22:31 ` [PATCH 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
2013-03-21 22:31 ` [PATCH 02/13] gatttool: Remove programming error check Alvaro Silva
2013-03-22  1:06   ` Anderson Lizardo
2013-03-21 22:31 ` [PATCH 03/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
2013-03-21 22:31 ` [PATCH 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
2013-03-21 22:31 ` [PATCH 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
2013-03-21 22:31 ` [PATCH 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
2013-03-21 22:31 ` [PATCH 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
2013-03-21 22:31 ` [PATCH 08/13] gatttool: Show connection state using color Alvaro Silva
2013-03-21 22:31 ` [PATCH 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
2013-03-21 22:31 ` [PATCH 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
2013-03-21 22:31 ` [PATCH 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
2013-03-21 22:31 ` [PATCH 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
2013-03-21 22:31 ` [PATCH 13/13] gatttool: Use error message prefixes consistently Alvaro Silva
2013-04-02 23:31 ` [PATCH BlueZ v2 00/13] Improvements on gatttool interactive interface Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 01/13] gatttool: Fix memory leak after parsing input line Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 02/13] gatttool: Remote address is mandatory for non-interactive gatttool Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 03/13] gatttool: Remove check for bluetooth address parameter on gatt_connect() Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 04/13] gatttool: Use GError to propage error messages to caller Alvaro Silva
2013-04-09 14:26     ` Johan Hedberg
2013-04-16 15:49     ` [PATCH BlueZ v3] " Eder Ruiz Maria
2013-04-17  8:24       ` Johan Hedberg
2013-04-02 23:31   ` [PATCH BlueZ v2 05/13] gatttool: Fix issues with printf() and readline prompt Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 06/13] gatttool: Replace more usages of printf() with rl_printf() Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 07/13] gatttool: Use bluetoothctl behavior when pressing Enter on empty prompt Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 08/13] gatttool: Show connection state using color Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 09/13] gatttool: Remove connecting message from prompt Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 10/13] gatttool: Use bluetoothctl strategy to handle standard input Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 11/13] gatttool: Use bluetoothctl strategy for unix signal handling Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 12/13] gatttool: Show info message when no primary service is found Alvaro Silva
2013-04-02 23:31   ` [PATCH BlueZ v2 13/13] gatttool: Use error message prefixes consistently Alvaro Silva

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.