Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH_v3 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-29  9:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383040097-15475-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index 913dab4..3479f80 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -278,6 +278,28 @@ static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t bt_hid_disconnect(struct hal_cmd_hid_disconnect *cmd,
+								uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	hid_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -287,6 +309,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = bt_hid_disconnect(buf,	len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v3 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-29  9:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
v3: Updated patches as per Luiz comments (remove unnecessary
    type cast and tabs)

v2: Updated patches as per Luiz comments

v1: Patchset adds hid connect and disconnect mechanisms at
    L2CAP level. It opens the control channel and interrupt
    channel and listens on io events. UHID, hid server and
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  245 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..913dab4 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,260 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct hid_device {
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct hid_device *hdev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&hdev->dst, dst);
+}
+
+static void hid_device_free(struct hid_device *hdev)
+{
+	if (hdev->ctrl_watch > 0)
+		g_source_remove(hdev->ctrl_watch);
+
+	if (hdev->intr_watch > 0)
+		g_source_remove(hdev->intr_watch);
+
+	if (hdev->intr_io)
+		g_io_channel_unref(hdev->intr_io);
+
+	if (hdev->ctrl_io)
+		g_io_channel_unref(hdev->ctrl_io);
+
+	devices = g_slist_remove(devices, hdev);
+	g_free(hdev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->intr_watch = 0;
+
+	if (hdev->intr_io) {
+		g_io_channel_unref(hdev->intr_io);
+		hdev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (hdev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->ctrl_watch = 0;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+
+	if (hdev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	hdev->intr_watch = g_io_add_watch(hdev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, hdev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(hdev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(hdev->intr_io);
+	hdev->intr_io = NULL;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	hdev->intr_io = bt_io_connect(interrupt_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!hdev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	hdev->ctrl_watch = g_io_add_watch(hdev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, hdev);
+
+	return;
+
+failed:
+	g_io_channel_unref(hdev->ctrl_io);
+	hdev->ctrl_io = NULL;
+}
+
+static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct hid_device *hdev;
+	char addr[18];
+	bdaddr_t dst;
+	GSList *l;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return HAL_STATUS_FAILED;
+
+	hdev = g_new0(struct hid_device, 1);
+	android2bdaddr(&cmd->bdaddr, &hdev->dst);
+	ba2str(&hdev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	hdev->ctrl_io = bt_io_connect(control_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		hid_device_free(hdev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, hdev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +284,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v2 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-29  8:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383035920-21599-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index 7f9e386..0a26bfe 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -278,6 +278,28 @@ static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t bt_hid_disconnect(struct hal_cmd_hid_disconnect *cmd,
+								uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	hid_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -287,6 +309,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = bt_hid_disconnect(buf,	len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v2 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-29  8:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
v2: Updated patches as per Luiz comments

v1: Patchset adds hid connect and disconnect mechanisms at
    L2CAP level. It opens the control channel and interrupt
    channel and listens on io events. UHID, hid server and
    reconnect related features not yet done.
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  245 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..7f9e386 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,260 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct hid_device {
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct hid_device *hdev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&hdev->dst, dst);
+}
+
+static void hid_device_free(struct hid_device *hdev)
+{
+	if (hdev->ctrl_watch > 0)
+		g_source_remove(hdev->ctrl_watch);
+
+	if (hdev->intr_watch > 0)
+		g_source_remove(hdev->intr_watch);
+
+	if (hdev->intr_io)
+		g_io_channel_unref(hdev->intr_io);
+
+	if (hdev->ctrl_io)
+		g_io_channel_unref(hdev->ctrl_io);
+
+	devices = g_slist_remove(devices, hdev);
+	g_free(hdev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(-errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->intr_watch = 0;
+
+	if (hdev->intr_io) {
+		g_io_channel_unref(hdev->intr_io);
+		hdev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (hdev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->ctrl_watch = 0;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+
+	if (hdev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	hdev->intr_watch = g_io_add_watch(hdev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, hdev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(hdev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(hdev->intr_io);
+	hdev->intr_io = NULL;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	hdev->intr_io = bt_io_connect(interrupt_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!hdev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	hdev->ctrl_watch = g_io_add_watch(hdev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, hdev);
+
+	return;
+
+failed:
+	g_io_channel_unref(hdev->ctrl_io);
+	hdev->ctrl_io = NULL;
+}
+
+static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct hid_device *hdev;
+	char addr[18];
+	bdaddr_t dst;
+	GSList *l;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return HAL_STATUS_FAILED;
+
+	hdev = g_new0(struct hid_device, 1);
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &hdev->dst);
+	ba2str(&hdev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	hdev->ctrl_io = bt_io_connect(control_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		hid_device_free(hdev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, hdev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +284,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* Re: Bluetooth tools
From: Vinicius Costa Gomes @ 2013-10-28 19:18 UTC (permalink / raw)
  To: Kevin Wilson; +Cc: linux-bluetooth
In-Reply-To: <CAGXs5wULS_dYYCCyimg3y9Fv6smMp8kOQbN3BfYJ+=bBhbhHxQ@mail.gmail.com>

Hi Kevin,

On 09:40 Sat 26 Oct, Kevin Wilson wrote:
> Hello,
> 
> I saw that bluetoothctl and btmon are the newer tool of Bluetooth.
> 
> What are the advantages of bluetoothctl over hciconfig/hcitool?

I would not say advantages, as they have very different aims, bluetoothctl is
meant to be used in the day-to-day (think scanning for a device, pairing
with it, changing the discoverability, etc); hciconfig/hcitool are more for
development/debugging (think disabling SSP mode, enabling periodic inquiry,
etc), they are more similar to btmgmt than to bluetoothctl.

> 
> What are the advantages of btmon over hcidump ?

btmon also tracks events from the Management interface. And colors ;-)

> 
> 
> Regards,
> Kevin
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
-- 
Vinicius

^ permalink raw reply

* [PATCH] build: Move Makefile.android to android/Makefile.am
From: Szymon Janc @ 2013-10-28 16:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This will keep all Android related changes within android directory.
---

Will also fix messing with Marcel's tab completion habits :-)

 Makefile.am         |   2 +-
 Makefile.android    | 113 ----------------------------------------------------
 android/Makefile.am | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 114 deletions(-)
 delete mode 100644 Makefile.android
 create mode 100644 android/Makefile.am

diff --git a/Makefile.am b/Makefile.am
index 8aed6f7..69a2805 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,7 +179,7 @@ test_scripts =
 
 include Makefile.tools
 include Makefile.obexd
-include Makefile.android
+include android/Makefile.am
 
 if HID2HCI
 rulesdir = @UDEV_DIR@/rules.d
diff --git a/Makefile.android b/Makefile.android
deleted file mode 100644
index 2b57daa..0000000
--- a/Makefile.android
+++ /dev/null
@@ -1,113 +0,0 @@
-if ANDROID
-noinst_PROGRAMS += android/bluetoothd
-
-android_bluetoothd_SOURCES =	android/main.c \
-				src/log.c \
-				android/hal-msg.h \
-				android/utils.h \
-				src/sdpd-database.c src/sdpd-server.c \
-				src/sdpd-service.c src/sdpd-request.c \
-				src/shared/util.h src/shared/util.c \
-				src/shared/mgmt.h src/shared/mgmt.c \
-				android/adapter.h android/adapter.c \
-				android/hid.h android/hid.c \
-				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
-
-android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
-
-noinst_LTLIBRARIES += android/libhal-internal.la
-
-android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
-					android/hal-sock.c \
-					android/hal-hidhost.c \
-					android/hal-pan.c \
-					android/hal-av.c \
-					android/hardware/bluetooth.h \
-					android/hardware/bt_av.h \
-					android/hardware/bt_gatt.h \
-					android/hardware/bt_gatt_client.h \
-					android/hardware/bt_gatt_server.h \
-					android/hardware/bt_gatt_types.h \
-					android/hardware/bt_hf.h \
-					android/hardware/bt_hh.h \
-					android/hardware/bt_hl.h \
-					android/hardware/bt_pan.h \
-					android/hardware/bt_rc.h \
-					android/hardware/bt_sock.h \
-					android/hardware/hardware.h \
-					android/cutils/properties.h \
-					android/hal-log.h \
-					android/hal-ipc.h android/hal-ipc.c
-
-android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android
-
-noinst_PROGRAMS += android/haltest
-
-android_haltest_SOURCES = android/client/haltest.c \
-				android/client/pollhandler.c \
-				android/client/terminal.c \
-				android/client/history.c \
-				android/client/textconv.c \
-				android/client/tabcompletion.c \
-				android/client/if-av.c \
-				android/client/if-bt.c \
-				android/client/if-hf.c \
-				android/client/if-hh.c \
-				android/client/if-pan.c \
-				android/client/if-sock.c \
-				android/client/hwmodule.c
-
-android_haltest_LDADD = android/libhal-internal.la
-
-android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
-
-android_haltest_LDFLAGS = -pthread
-
-endif
-
-EXTRA_DIST += android/Android.mk android/device.c android/adapter.c\
-		android/main.c android/hal-msg.h android/hal.h
-
-EXTRA_DIST += android/hal-bluetooth.c \
-		android/hal-sock.c \
-		android/hal-hidhost.c \
-		android/hal-pan.c \
-		android/hal-av.c \
-		android/hal-log.h
-
-EXTRA_DIST += android/client/terminal.c \
-		android/client/haltest.c \
-		android/client/hwmodule.c \
-		android/client/pollhandler.c \
-		android/client/history.c \
-		android/client/if-av.c \
-		android/client/if-bt.c \
-		android/client/if-hf.c \
-		android/client/if-hh.c \
-		android/client/if-pan.c \
-		android/client/if-sock.c \
-		android/client/textconv.c \
-		android/client/tabcompletion.c \
-		android/client/textconv.h \
-		android/client/if-main.h \
-		android/client/pollhandler.h \
-		android/client/history.h \
-		android/client/terminal.h
-
-EXTRA_DIST += android/hal-ipc-api.txt
-
-EXTRA_DIST += android/hardware/bluetooth.h \
-		android/hardware/bt_av.h \
-		android/hardware/bt_gatt.h \
-		android/hardware/bt_gatt_client.h \
-		android/hardware/bt_gatt_server.h \
-		android/hardware/bt_gatt_types.h \
-		android/hardware/bt_hf.h \
-		android/hardware/bt_hh.h \
-		android/hardware/bt_hl.h \
-		android/hardware/bt_pan.h \
-		android/hardware/bt_rc.h \
-		android/hardware/bt_sock.h \
-		android/hardware/hardware.h \
-		android/cutils/properties.h
diff --git a/android/Makefile.am b/android/Makefile.am
new file mode 100644
index 0000000..2b57daa
--- /dev/null
+++ b/android/Makefile.am
@@ -0,0 +1,113 @@
+if ANDROID
+noinst_PROGRAMS += android/bluetoothd
+
+android_bluetoothd_SOURCES =	android/main.c \
+				src/log.c \
+				android/hal-msg.h \
+				android/utils.h \
+				src/sdpd-database.c src/sdpd-server.c \
+				src/sdpd-service.c src/sdpd-request.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/mgmt.h src/shared/mgmt.c \
+				android/adapter.h android/adapter.c \
+				android/hid.h android/hid.c \
+				android/ipc.h android/ipc.c \
+				android/socket.h android/socket.c
+
+android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
+noinst_LTLIBRARIES += android/libhal-internal.la
+
+android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
+					android/hal-sock.c \
+					android/hal-hidhost.c \
+					android/hal-pan.c \
+					android/hal-av.c \
+					android/hardware/bluetooth.h \
+					android/hardware/bt_av.h \
+					android/hardware/bt_gatt.h \
+					android/hardware/bt_gatt_client.h \
+					android/hardware/bt_gatt_server.h \
+					android/hardware/bt_gatt_types.h \
+					android/hardware/bt_hf.h \
+					android/hardware/bt_hh.h \
+					android/hardware/bt_hl.h \
+					android/hardware/bt_pan.h \
+					android/hardware/bt_rc.h \
+					android/hardware/bt_sock.h \
+					android/hardware/hardware.h \
+					android/cutils/properties.h \
+					android/hal-log.h \
+					android/hal-ipc.h android/hal-ipc.c
+
+android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android
+
+noinst_PROGRAMS += android/haltest
+
+android_haltest_SOURCES = android/client/haltest.c \
+				android/client/pollhandler.c \
+				android/client/terminal.c \
+				android/client/history.c \
+				android/client/textconv.c \
+				android/client/tabcompletion.c \
+				android/client/if-av.c \
+				android/client/if-bt.c \
+				android/client/if-hf.c \
+				android/client/if-hh.c \
+				android/client/if-pan.c \
+				android/client/if-sock.c \
+				android/client/hwmodule.c
+
+android_haltest_LDADD = android/libhal-internal.la
+
+android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_haltest_LDFLAGS = -pthread
+
+endif
+
+EXTRA_DIST += android/Android.mk android/device.c android/adapter.c\
+		android/main.c android/hal-msg.h android/hal.h
+
+EXTRA_DIST += android/hal-bluetooth.c \
+		android/hal-sock.c \
+		android/hal-hidhost.c \
+		android/hal-pan.c \
+		android/hal-av.c \
+		android/hal-log.h
+
+EXTRA_DIST += android/client/terminal.c \
+		android/client/haltest.c \
+		android/client/hwmodule.c \
+		android/client/pollhandler.c \
+		android/client/history.c \
+		android/client/if-av.c \
+		android/client/if-bt.c \
+		android/client/if-hf.c \
+		android/client/if-hh.c \
+		android/client/if-pan.c \
+		android/client/if-sock.c \
+		android/client/textconv.c \
+		android/client/tabcompletion.c \
+		android/client/textconv.h \
+		android/client/if-main.h \
+		android/client/pollhandler.h \
+		android/client/history.h \
+		android/client/terminal.h
+
+EXTRA_DIST += android/hal-ipc-api.txt
+
+EXTRA_DIST += android/hardware/bluetooth.h \
+		android/hardware/bt_av.h \
+		android/hardware/bt_gatt.h \
+		android/hardware/bt_gatt_client.h \
+		android/hardware/bt_gatt_server.h \
+		android/hardware/bt_gatt_types.h \
+		android/hardware/bt_hf.h \
+		android/hardware/bt_hh.h \
+		android/hardware/bt_hl.h \
+		android/hardware/bt_pan.h \
+		android/hardware/bt_rc.h \
+		android/hardware/bt_sock.h \
+		android/hardware/hardware.h \
+		android/cutils/properties.h
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH] android/hal: Set callbacks before initializing IPC
From: Szymon Janc @ 2013-10-28 15:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Notification thread is started on IPC init and it can be scheduled
before main thread.

Fix following crash on HAL init:

pid: 3392, tid: 3492, name: droid.bluetooth  >>> com.android.bluetooth <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000028
    eax 00000000  ebx ce047f64  ecx ce0405d0  edx f7763724
    esi cdf3af00  edi f837fb90
    xcs 00000023  xds 0000002b  xes 0000002b  xfs 00000000  xss 0000002b
    eip ce042289  ebp cdf3a9f8  esp cdf3a9e0  flags 00010292

backtrace:
    #00  pc 00003289  /system/lib/hw/bluetooth.default.so (bt_thread_associate+25)
    #01  pc 000015f8  /system/lib/hw/bluetooth.default.so (notification_handler+40)
    #02  pc 0000f804  /system/lib/libc.so (__thread_entry+276)
    #03  pc 0002999d  /system/lib/libc.so
    #04  pc 00082ae7  /system/lib/libdvm.so (dvmThreadSelf()+39)
    #05  pc 00010db9  /system/lib/libc.so (pthread_mutex_unlock+25)
---
 android/hal-bluetooth.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 5929fff..5f6dcbe 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -114,11 +114,13 @@ static int init(bt_callbacks_t *callbacks)
 	if (interface_ready())
 		return BT_STATUS_SUCCESS;
 
-	if (!hal_ipc_init())
-		return BT_STATUS_FAIL;
-
 	bt_hal_cbacks = callbacks;
 
+	if (!hal_ipc_init()) {
+		bt_hal_cbacks = NULL;
+		return BT_STATUS_FAIL;
+	}
+
 	cmd.service_id = HAL_SERVICE_ID_BLUETOOTH;
 
 	status = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 2/2] android: Use thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 15:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382974225-13855-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Make use of thread-safe helpers.
---
 android/client/textconv.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 1dc6ad0..c09f47d 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <hardware/bluetooth.h>
 
+#include "../pthread-local.h"
+
 #include "textconv.h"
 
 /*
@@ -227,11 +229,12 @@ const char *enum_one_string(void *v, int i)
 	return (i == 0) && (m[0] != 0) ? m : NULL;
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(bdaddr_buf);
 char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 {
-	static char buf[MAX_ADDR_STR_LEN];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, bdaddr_buf, MAX_ADDR_STR_LEN);
 
-	return bt_bdaddr_t2str(bd_addr, buf);
+	return bt_bdaddr_t2str(bd_addr, bdaddr_buf_tls_buffer);
 }
 
 static char *btuuid2str(const bt_uuid_t *uuid)
@@ -241,12 +244,14 @@ static char *btuuid2str(const bt_uuid_t *uuid)
 	return bt_uuid_t2str(uuid, buf);
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(property_buf);
 char *btproperty2str(const bt_property_t *property)
 {
-	static char buf[4096];
 	char *p;
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, property_buf, 4096);
 
-	p = buf + sprintf(buf, "type=%s len=%d val=",
+	p = property_buf_tls_buffer + sprintf(property_buf_tls_buffer,
+					"type=%s len=%d val=",
 					bt_property_type_t2str(property->type),
 					property->len);
 
@@ -334,5 +339,5 @@ char *btproperty2str(const bt_property_t *property)
 		sprintf(p, "%p", property->val);
 	}
 
-	return buf;
+	return property_buf_tls_buffer;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 1/2] android: Add thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 15:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Add thread safe helpers to make HAL debug printing thread-safe. The code
is inherited from Android bionic and it is used for strerror, strsignal,
etc.
---
 android/pthread-local.h |   53 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 android/pthread-local.h

diff --git a/android/pthread-local.h b/android/pthread-local.h
new file mode 100644
index 0000000..4bf22f3
--- /dev/null
+++ b/android/pthread-local.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
+  static pthread_key_t __bionic_tls_ ## name ## _key; \
+  static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
+    free(buffer); \
+  } \
+  __attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \
+    pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \
+  }
+
+/*
+ * Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
+ */
+#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
+  const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count; \
+  type name ## _tls_buffer = \
+      (pthread_getspecific(__bionic_tls_ ## name ## _key)); \
+  if (name ## _tls_buffer == NULL) { \
+    name ## _tls_buffer = (calloc(1, byte_count)); \
+    pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \
+  }
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH 1/2] android: Add initial HID connect implementation
From: Luiz Augusto von Dentz @ 2013-10-28 15:06 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1382971653-11727-2-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Mon, Oct 28, 2013 at 4:47 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> Implemented basic HID connect method. Host connects to
> bt device at L2CAP level.
> ---
>  Makefile.android   |    3 +-
>  android/Android.mk |    1 +
>  android/hid.c      |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 240 insertions(+), 1 deletion(-)
>
> diff --git a/Makefile.android b/Makefile.android
> index 2b57daa..22002be 100644
> --- a/Makefile.android
> +++ b/Makefile.android
> @@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =  android/main.c \
>                                 android/adapter.h android/adapter.c \
>                                 android/hid.h android/hid.c \
>                                 android/ipc.h android/ipc.c \
> -                               android/socket.h android/socket.c
> +                               android/socket.h android/socket.c \
> +                               btio/btio.h btio/btio.c
>
>  android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
>
> diff --git a/android/Android.mk b/android/Android.mk
> index 22208e0..28ec465 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
>         ../lib/sdp.c \
>         ../lib/bluetooth.c \
>         ../lib/hci.c \
> +       ../btio/btio.c
>
>  LOCAL_C_INCLUDES := \
>         $(call include-path-for, glib) \
> diff --git a/android/hid.c b/android/hid.c
> index f2da0d3..b7bdc07 100644
> --- a/android/hid.c
> +++ b/android/hid.c
> @@ -23,16 +23,252 @@
>
>  #include <stdint.h>
>  #include <stdbool.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <fcntl.h>
>
>  #include <glib.h>
>
> +#include "btio/btio.h"
>  #include "lib/bluetooth.h"
> +#include "src/shared/mgmt.h"
> +
>  #include "log.h"
>  #include "hal-msg.h"
>  #include "ipc.h"
>  #include "hid.h"
> +#include "adapter.h"
> +#include "utils.h"
> +
> +#define L2CAP_PSM_HIDP_CTRL    0x11
> +#define L2CAP_PSM_HIDP_INTR    0x13
> +#define MAX_READ_BUFFER                4096
>
>  static GIOChannel *notification_io = NULL;
> +static GSList *devices = NULL;
> +
> +struct input_device {
> +       bdaddr_t        src;
> +       bdaddr_t        dst;
> +       GIOChannel      *ctrl_io;
> +       GIOChannel      *intr_io;
> +       guint           ctrl_watch;
> +       guint           intr_watch;
> +};


You probably don't need the address of the adapter as there could be
only one in android you can always query its value via
bt_adapter_get_address.

> +static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
> +{
> +       struct input_device *idev;
> +       char addr[18];
> +       GError *err = NULL;
> +
> +       DBG("");
> +
> +       if (len < sizeof(*cmd))
> +               return HAL_STATUS_INVALID;
> +
> +       idev = g_new0(struct input_device, 1);
> +       bacpy(&idev->src, bt_adapter_get_address());
> +       android2bdaddr((bdaddr_t *)&cmd->bdaddr, &idev->dst);
> +       ba2str(&idev->dst, addr);

Might be worth checking if there a connection ongoing before you
create a new data, I would also avoid having the same struct names
from our input plugin, just use something else like hid_data.

> +
> +       DBG("connecting to %s", addr);
> +
> +       idev->ctrl_io = bt_io_connect(control_connect_cb, idev, NULL, &err,
> +                                       BT_IO_OPT_SOURCE_BDADDR, &idev->src,
> +                                       BT_IO_OPT_DEST_BDADDR, &idev->dst,
> +                                       BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
> +                                       BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> +                                       BT_IO_OPT_INVALID);
> +       if (err) {
> +               error("%s", err->message);
> +               g_error_free(err);
> +               input_device_free(idev);
> +               return HAL_STATUS_FAILED;
> +       }
> +
> +       devices = g_slist_append(devices, idev);
> +
> +       return HAL_STATUS_SUCCESS;
> +}
>
>  void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>  {
> @@ -40,6 +276,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>
>         switch (opcode) {
>         case HAL_OP_HID_CONNECT:
> +               status = dev_connect((struct hal_cmd_hid_connect *) buf, len);

Call it hid_connect or bt_hid_connect.



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] Regression fix revert: "Bluetooth: Add missing reset_resume dev_pm_ops"
From: Hans de Goede @ 2013-10-28 14:54 UTC (permalink / raw)
  To: Gustavo Padovan
  Cc: USB list, linux-bluetooth, Shuah Khan, Gustavo Padovan, stable
In-Reply-To: <508150F6-D142-4406-8CC9-57DDE754F391@holtmann.org>

Hi Gustavo,

> Patch has been applied to bluetooth.git. Thanks.

Hmm, I'm not seeing this in 3.12 yet, not only should this be added
to 3.12 asap, it should also really get added to 3.11.x soon.

The regression this patch fixes is breaking btusb for lots of users, see:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1213239
https://bugzilla.redhat.com/show_bug.cgi?id=988481

Where lots of people are adding me too comments (and some are building
their own kernels with the revert and confirming it fixes things for
them).

Regards,

Hans

^ permalink raw reply

* Re: [PATCH 2/2] android: Add initial HID disconnect implementation.
From: Luiz Augusto von Dentz @ 2013-10-28 14:53 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1382971653-11727-3-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Mon, Oct 28, 2013 at 4:47 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> Implemented basic HID disconnect method. Host disconnects
> with bt device at L2CAP level.
> ---
>  android/hid.c |   23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>
> diff --git a/android/hid.c b/android/hid.c
> index b7bdc07..3e7ac0d 100644
> --- a/android/hid.c
> +++ b/android/hid.c
> @@ -270,6 +270,27 @@ static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
>         return HAL_STATUS_SUCCESS;
>  }
>
> +static uint8_t dev_disconnect(struct hal_cmd_hid_disconnect *cmd, uint16_t len)
> +{
> +       GSList *l;
> +       bdaddr_t dst;
> +
> +       DBG("");
> +
> +       if (len < sizeof(*cmd))
> +               return HAL_STATUS_INVALID;
> +
> +       android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
> +
> +       l = g_slist_find_custom(devices, &dst, device_cmp);
> +       if (!l)
> +               return HAL_STATUS_FAILED;
> +
> +       input_device_free(l->data);
> +
> +       return HAL_STATUS_SUCCESS;
> +}
> +
>  void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>  {
>         uint8_t status = HAL_STATUS_FAILED;
> @@ -279,6 +300,8 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>                 status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
>                 break;
>         case HAL_OP_HID_DISCONNECT:
> +               status = dev_disconnect((struct hal_cmd_hid_disconnect *) buf,
> +                                                                       len);

Look at the other files, we are not doing the casts upfront but in the
function itself.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1382971653-11727-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index b7bdc07..3e7ac0d 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -270,6 +270,27 @@ static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t dev_disconnect(struct hal_cmd_hid_disconnect *cmd, uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	input_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -279,6 +300,8 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = dev_disconnect((struct hal_cmd_hid_disconnect *) buf,
+									len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1382971653-11727-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 240 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..b7bdc07 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,252 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct input_device {
+	bdaddr_t	src;
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct input_device *idev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&idev->dst, dst);
+}
+
+static void input_device_free(struct input_device *idev)
+{
+	if (idev->ctrl_watch > 0)
+		g_source_remove(idev->ctrl_watch);
+
+	if (idev->intr_watch > 0)
+		g_source_remove(idev->intr_watch);
+
+	if (idev->intr_io)
+		g_io_channel_unref(idev->intr_io);
+
+	if (idev->ctrl_io)
+		g_io_channel_unref(idev->ctrl_io);
+
+	devices = g_slist_remove(devices, idev);
+	g_free(idev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(-errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct input_device *idev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&idev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	idev->intr_watch = 0;
+
+	if (idev->intr_io) {
+		g_io_channel_unref(idev->intr_io);
+		idev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (idev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct input_device *idev = data;
+	char address[18];
+
+	ba2str(&idev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	idev->ctrl_watch = 0;
+
+	if (idev->ctrl_io) {
+		g_io_channel_unref(idev->ctrl_io);
+		idev->ctrl_io = NULL;
+	}
+
+	if (idev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	idev->intr_watch = g_io_add_watch(idev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, idev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(idev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(idev->intr_io);
+	idev->intr_io = NULL;
+
+	if (idev->ctrl_io) {
+		g_io_channel_unref(idev->ctrl_io);
+		idev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+	GError *err = NULL;
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	idev->intr_io = bt_io_connect(interrupt_connect_cb, idev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &idev->src,
+					BT_IO_OPT_DEST_BDADDR, &idev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!idev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	idev->ctrl_watch = g_io_add_watch(idev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, idev);
+
+	return;
+
+failed:
+	g_io_channel_unref(idev->ctrl_io);
+	idev->ctrl_io = NULL;
+}
+
+static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct input_device *idev;
+	char addr[18];
+	GError *err = NULL;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	idev = g_new0(struct input_device, 1);
+	bacpy(&idev->src, bt_adapter_get_address());
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &idev->dst);
+	ba2str(&idev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	idev->ctrl_io = bt_io_connect(control_connect_cb, idev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &idev->src,
+					BT_IO_OPT_DEST_BDADDR, &idev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		input_device_free(idev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, idev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +276,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 0/2] Initial HID connect disconnect methods
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Patchset adds hid connect and disconnect mechanisms at
L2CAP level. It opens the control channel and interrupt
channel and listens on io events. UHID, hid server and
reconnect related features not yet done.

Ravi kumar Veeramally (2):
  android: Add initial HID connect implementation
  android: Add initial HID disconnect implementation.

 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  260 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+), 1 deletion(-)

-- 
1.7.9.5


^ permalink raw reply

* [RFC 2/2] android: Use thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Make use of thread-safe helpers.
---
 android/client/textconv.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 16392c2..6e75c28 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <hardware/bluetooth.h>
 
+#include "../pthread-local.h"
+
 #include "textconv.h"
 
 /*
@@ -227,11 +229,12 @@ const char *enum_one_string(void *v, int i)
 	return (i == 0) && (m[0] != 0) ? m : NULL;
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(bdaddr_buf);
 char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 {
-	static char buf[MAX_ADDR_STR_LEN];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, bdaddr_buf, MAX_ADDR_STR_LEN);
 
-	return bt_bdaddr_t2str(bd_addr, buf);
+	return bt_bdaddr_t2str(bd_addr, bdaddr_buf_tls_buffer);
 }
 
 char *btuuid2str(const bt_uuid_t *uuid)
@@ -241,12 +244,14 @@ char *btuuid2str(const bt_uuid_t *uuid)
 	return bt_uuid_t2str(uuid, buf);
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(property_buf);
 char *btproperty2str(const bt_property_t *property)
 {
-	static char buf[4096];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, property_buf, 4096);
 	char *p;
 
-	p = buf + sprintf(buf, "type=%s len=%d val=",
+	p = property_buf_tls_buffer + sprintf(property_buf_tls_buffer,
+					"type=%s len=%d val=",
 					bt_property_type_t2str(property->type),
 					property->len);
 
@@ -334,5 +339,5 @@ char *btproperty2str(const bt_property_t *property)
 		sprintf(p, "%p", property->val);
 	}
 
-	return buf;
+	return property_buf_tls_buffer;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 1/2] android: Add thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Add thread safe helpers to make HAL debug printing thread-safe. The code
is inherited from Android bionic and it is used for strerror, strsignal,
etc.
---
 android/pthread-local.h |   51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 android/pthread-local.h

diff --git a/android/pthread-local.h b/android/pthread-local.h
new file mode 100644
index 0000000..07012f3
--- /dev/null
+++ b/android/pthread-local.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <pthread.h>
+
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
+  static pthread_key_t __bionic_tls_ ## name ## _key; \
+  static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
+    free(buffer); \
+  } \
+  __attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \
+    pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \
+  }
+
+// Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
+#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
+  type name ## _tls_buffer = \
+      (pthread_getspecific(__bionic_tls_ ## name ## _key)); \
+  if (name ## _tls_buffer == NULL) { \
+    name ## _tls_buffer = (calloc(1, byte_count)); \
+    pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \
+  } \
+  const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 0/2] Make HAL debug thread-safe
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Since HAL is threaded this makes it safe to print properties and bdaddr.
This is slightly modified bionic thread-safe code.

Please comment.

Andrei Emeltchenko (2):
  android: Add thread-safe helpers
  android: Use thread-safe helpers

 android/client/textconv.c |   15 ++++++++-----
 android/pthread-local.h   |   51 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 5 deletions(-)
 create mode 100644 android/pthread-local.h

-- 
1.7.10.4


^ permalink raw reply

* Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface
From: Marcel Holtmann @ 2013-10-28 13:47 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: Marcin Kraglak, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131028132354.GA13148@x220.p-661hnu-f1>

Hi Johan,

>> +static int uuid_cmp(const void *a, const void *b)
>> +{
>> +	const sdp_record_t *rec = a;
>> +	const uuid_t *uuid = b;
>> +
>> +	return sdp_uuid_cmp(&rec->svclass, uuid);
>> +}
>> +
>> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
>> +{
>> +	if (uuid->type == SDP_UUID16)
>> +		sdp_uuid16_to_uuid128(uuid128, uuid);
>> +	else if (uuid->type == SDP_UUID32)
>> +		sdp_uuid32_to_uuid128(uuid128, uuid);
>> +	else
>> +		memcpy(uuid128, uuid, sizeof(*uuid));
>> +}
>> +
>> +static uint8_t get_uuid_mask(const uuid_t *uuid)
>> +{
>> +	if (uuid->type != SDP_UUID16)
>> +		return 0;
>> +
>> +	switch (uuid->value.uuid16) {
>> +	case DIALUP_NET_SVCLASS_ID:
>> +	case CIP_SVCLASS_ID:
>> +		return 0x42;    /* Telephony & Networking */
>> +	case IRMC_SYNC_SVCLASS_ID:
>> +	case OBEX_OBJPUSH_SVCLASS_ID:
>> +	case OBEX_FILETRANS_SVCLASS_ID:
>> +	case IRMC_SYNC_CMD_SVCLASS_ID:
>> +	case PBAP_PSE_SVCLASS_ID:
>> +		return 0x10;    /* Object Transfer */
>> +	case HEADSET_SVCLASS_ID:
>> +	case HANDSFREE_SVCLASS_ID:
>> +		return 0x20;    /* Audio */
>> +	case CORDLESS_TELEPHONY_SVCLASS_ID:
>> +	case INTERCOM_SVCLASS_ID:
>> +	case FAX_SVCLASS_ID:
>> +	case SAP_SVCLASS_ID:
>> +	/*
>> +	* Setting the telephony bit for the handsfree audio gateway
>> +	* role is not required by the HFP specification, but the
>> +	* Nokia 616 carkit is just plain broken! It will refuse
>> +	* pairing without this bit set.
>> +	*/
>> +	case HANDSFREE_AGW_SVCLASS_ID:
>> +		return 0x40;    /* Telephony */
>> +	case AUDIO_SOURCE_SVCLASS_ID:
>> +	case VIDEO_SOURCE_SVCLASS_ID:
>> +		return 0x08;    /* Capturing */
>> +	case AUDIO_SINK_SVCLASS_ID:
>> +	case VIDEO_SINK_SVCLASS_ID:
>> +		return 0x04;    /* Rendering */
>> +	case PANU_SVCLASS_ID:
>> +	case NAP_SVCLASS_ID:
>> +	case GN_SVCLASS_ID:
>> +		return 0x02;    /* Networking */
>> +	default:
>> +		return 0;
>> +	}
>> +}
> 
> I don't think it makes sense to duplicate this code in bluez.git,
> especially not the last function. Instead, I think it should be
> refactored to the appropriate common place (lib/sdp.c maybe? Or maybe
> not if we don't want to pollute the already deprecated libbluetooth - in
> which case I'd expect a proposal where to put this).

I was actually thinking that we just make this static. In Android all SDP records are normally registered ahead of time. They even did this when they used BlueZ. It was essentially a sdptool add for all the records they needed.

This is also means we can just use the service class hint as a static value.

>> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
>> +{
>> +	struct mgmt_cp_add_uuid cp;
>> +	uuid_t uuid128;
>> +	uint128_t uint128;
>> +
>> +	uuid_to_uuid128(&uuid128, uuid);
>> +
>> +	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
>> +	htob128(&uint128, (uint128_t *) cp.uuid);
>> +	cp.svc_hint = svc_hint;
>> +
>> +	if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
>> +			0, sizeof(cp), &cp,
>> +			add_uuid_complete, adapter, NULL) > 0)
>> +		return 0;
> 
> Since you're skipping the "is_supported_uuid" check that we're doing in
> the normal bluetoothd I suppose we at least have a proper check for a
> minimum mgmt version when initializing the android bluetoothd? Otherwise
> your patch is broken.

We should require a minimum mgmt version for Android. One that has all the bugs fixed. There is no point in planning on supporting older kernels anyway.

Regards

Marcel


^ permalink raw reply

* [PATCH 2/2] android: Use helper function to convert bdaddr to android format
From: Szymon Janc @ 2013-10-28 13:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382967914-11102-1-git-send-email-szymon.janc@tieto.com>

This will make easier to understand why swap is needed.
---
 Makefile.android  | 1 +
 android/adapter.c | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index fd8043c..2b57daa 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -4,6 +4,7 @@ noinst_PROGRAMS += android/bluetoothd
 android_bluetoothd_SOURCES =	android/main.c \
 				src/log.c \
 				android/hal-msg.h \
+				android/utils.h \
 				src/sdpd-database.c src/sdpd-server.c \
 				src/sdpd-service.c src/sdpd-request.c \
 				src/shared/util.h src/shared/util.c \
diff --git a/android/adapter.c b/android/adapter.c
index f393c49..15b65e5 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -31,6 +31,7 @@
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
+#include "utils.h"
 #include "adapter.h"
 
 static GIOChannel *notification_io = NULL;
@@ -384,7 +385,7 @@ static void send_adapter_address(void)
 
 	ev->props[0].type = HAL_PROP_ADAPTER_ADDR;
 	ev->props[0].len = sizeof(bdaddr_t);
-	baswap((bdaddr_t *) ev->props[0].val, &adapter->bdaddr);
+	bdaddr2android(&adapter->bdaddr, ev->props[0].val);
 
 	ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
 				HAL_EV_ADAPTER_PROPS_CHANGED, len, ev, -1);
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 1/2] android: Add helper functions for converting bdaddr transmitted over IPC
From: Szymon Janc @ 2013-10-28 13:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Android holds Bluetooth address in reverse order comparing to
bluetoothd. Add convenient functions for converting to and from that
format.

Convertion will done on daemon side to keep HAL library simple.
---
 android/utils.h | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 android/utils.h

diff --git a/android/utils.h b/android/utils.h
new file mode 100644
index 0000000..5b009bc
--- /dev/null
+++ b/android/utils.h
@@ -0,0 +1,33 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+static inline void android2bdaddr(const void *buf, bdaddr_t *dst)
+{
+	baswap(dst, buf);
+}
+
+static inline void bdaddr2android(const bdaddr_t *src, void *buf)
+{
+	baswap(buf, src);
+}
-- 
1.8.4.1


^ permalink raw reply related

* Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface
From: Andrei Emeltchenko @ 2013-10-28 13:24 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1382963409-1012-5-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Mon, Oct 28, 2013 at 01:30:09PM +0100, Marcin Kraglak wrote:
> Use mgmt interface for adding and removing uuids to adapter.
> This is needed for proper changing adapter's class of device.
> ---
>  android/adapter.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 141 insertions(+)
> 
> diff --git a/android/adapter.c b/android/adapter.c
> index b1cb5f8..bed0423 100644
> --- a/android/adapter.c
> +++ b/android/adapter.c
> @@ -532,10 +532,105 @@ error:
>  	ipc_send_rsp(io, HAL_SERVICE_ID_BLUETOOTH, status);
>  }
>  
> +static int uuid_cmp(const void *a, const void *b)
> +{
> +	const sdp_record_t *rec = a;
> +	const uuid_t *uuid = b;
> +
> +	return sdp_uuid_cmp(&rec->svclass, uuid);
> +}
> +
> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> +{
> +	if (uuid->type == SDP_UUID16)
> +		sdp_uuid16_to_uuid128(uuid128, uuid);
> +	else if (uuid->type == SDP_UUID32)
> +		sdp_uuid32_to_uuid128(uuid128, uuid);
> +	else
> +		memcpy(uuid128, uuid, sizeof(*uuid));
> +}
> +
> +static uint8_t get_uuid_mask(const uuid_t *uuid)
> +{
> +	if (uuid->type != SDP_UUID16)
> +		return 0;
> +
> +	switch (uuid->value.uuid16) {
> +	case DIALUP_NET_SVCLASS_ID:
> +	case CIP_SVCLASS_ID:
> +		return 0x42;    /* Telephony & Networking */
> +	case IRMC_SYNC_SVCLASS_ID:
> +	case OBEX_OBJPUSH_SVCLASS_ID:
> +	case OBEX_FILETRANS_SVCLASS_ID:
> +	case IRMC_SYNC_CMD_SVCLASS_ID:
> +	case PBAP_PSE_SVCLASS_ID:
> +		return 0x10;    /* Object Transfer */
> +	case HEADSET_SVCLASS_ID:
> +	case HANDSFREE_SVCLASS_ID:
> +		return 0x20;    /* Audio */
> +	case CORDLESS_TELEPHONY_SVCLASS_ID:
> +	case INTERCOM_SVCLASS_ID:
> +	case FAX_SVCLASS_ID:
> +	case SAP_SVCLASS_ID:
> +	/*
> +	* Setting the telephony bit for the handsfree audio gateway
> +	* role is not required by the HFP specification, but the
> +	* Nokia 616 carkit is just plain broken! It will refuse
> +	* pairing without this bit set.
> +	*/
> +	case HANDSFREE_AGW_SVCLASS_ID:
> +		return 0x40;    /* Telephony */
> +	case AUDIO_SOURCE_SVCLASS_ID:
> +	case VIDEO_SOURCE_SVCLASS_ID:
> +		return 0x08;    /* Capturing */
> +	case AUDIO_SINK_SVCLASS_ID:
> +	case VIDEO_SINK_SVCLASS_ID:
> +		return 0x04;    /* Rendering */
> +	case PANU_SVCLASS_ID:
> +	case NAP_SVCLASS_ID:
> +	case GN_SVCLASS_ID:
> +		return 0x02;    /* Networking */
> +	default:
> +		return 0;
> +	}
> +}

Can those functions be reused between our android/adapter and src/adapter?

Best regards 
Andrei Emeltchenko 


> +
> +static void add_uuid_complete(uint8_t status, uint16_t length,
> +					const void *param, void *user_data)
> +{
> +	if (status != MGMT_STATUS_SUCCESS) {
> +		error("Failed to add UUID: %s (0x%02x)",
> +						mgmt_errstr(status), status);
> +		return;
> +	}
> +	/*TODO inform that adapter uuids has been changed*/
> +}
> +
> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
> +{
> +	struct mgmt_cp_add_uuid cp;
> +	uuid_t uuid128;
> +	uint128_t uint128;
> +
> +	uuid_to_uuid128(&uuid128, uuid);
> +
> +	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> +	htob128(&uint128, (uint128_t *) cp.uuid);
> +	cp.svc_hint = svc_hint;
> +
> +	if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
> +			0, sizeof(cp), &cp,
> +			add_uuid_complete, adapter, NULL) > 0)
> +		return 0;
> +
> +	return -EIO;
> +}
> +
>  static void adapter_service_insert(sdp_record_t *rec)
>  {
>  	sdp_list_t *browse_list = NULL;
>  	uuid_t browse_uuid;
> +	bool new_uuid;
>  
>  	/* skip record without a browse group */
>  	if (sdp_get_browse_groups(rec, &browse_list) < 0) {
> @@ -552,6 +647,19 @@ static void adapter_service_insert(sdp_record_t *rec)
>  	adapter->services = sdp_list_insert_sorted(
>  				adapter->services, rec, record_sort);
>  
> +	if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
> +		new_uuid = true;
> +	else
> +		new_uuid = false;
> +
> +	adapter->services = sdp_list_insert_sorted(adapter->services, rec,
> +							record_sort);
> +
> +	if (new_uuid) {
> +		uint8_t svc_hint = get_uuid_mask(&rec->svclass);
> +		add_uuid(&rec->svclass, svc_hint);
> +	}
> +
>  done:
>  	sdp_list_free(browse_list, free);
>  }
> @@ -569,6 +677,36 @@ int bt_adapter_service_add(sdp_record_t *rec)
>  	return ret;
>  }
>  
> +static void remove_uuid_complete(uint8_t status, uint16_t length,
> +				const void *param, void *user_data)
> +{
> +	if (status != MGMT_STATUS_SUCCESS) {
> +			error("Failed to remove UUID: %s (0x%02x)",
> +		mgmt_errstr(status), status);
> +		return;
> +	}
> +	/*TODO inform that adapter uuids has been changed*/
> +}
> +
> +static int remove_uuid(uuid_t *uuid)
> +{
> +	struct mgmt_cp_remove_uuid cp;
> +	uuid_t uuid128;
> +	uint128_t uint128;
> +
> +	uuid_to_uuid128(&uuid128, uuid);
> +
> +	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> +	htob128(&uint128, (uint128_t *) cp.uuid);
> +
> +	if (mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID,
> +			0, sizeof(cp), &cp,
> +			remove_uuid_complete, adapter, NULL) > 0)
> +		return 0;
> +
> +	return -EIO;
> +}
> +
>  void bt_adapter_service_remove(uint32_t handle)
>  {
>  	sdp_record_t *rec = sdp_record_find(handle);
> @@ -578,6 +716,9 @@ void bt_adapter_service_remove(uint32_t handle)
>  
>  	adapter->services = sdp_list_remove(adapter->services, rec);
>  
> +	if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
> +		remove_uuid(&rec->svclass);
> +
>  	remove_record_from_server(rec->handle);
>  }
>  
> -- 
> 1.8.2.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface
From: Johan Hedberg @ 2013-10-28 13:23 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1382963409-1012-5-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Mon, Oct 28, 2013, Marcin Kraglak wrote:
> +static int uuid_cmp(const void *a, const void *b)
> +{
> +	const sdp_record_t *rec = a;
> +	const uuid_t *uuid = b;
> +
> +	return sdp_uuid_cmp(&rec->svclass, uuid);
> +}
> +
> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> +{
> +	if (uuid->type == SDP_UUID16)
> +		sdp_uuid16_to_uuid128(uuid128, uuid);
> +	else if (uuid->type == SDP_UUID32)
> +		sdp_uuid32_to_uuid128(uuid128, uuid);
> +	else
> +		memcpy(uuid128, uuid, sizeof(*uuid));
> +}
> +
> +static uint8_t get_uuid_mask(const uuid_t *uuid)
> +{
> +	if (uuid->type != SDP_UUID16)
> +		return 0;
> +
> +	switch (uuid->value.uuid16) {
> +	case DIALUP_NET_SVCLASS_ID:
> +	case CIP_SVCLASS_ID:
> +		return 0x42;    /* Telephony & Networking */
> +	case IRMC_SYNC_SVCLASS_ID:
> +	case OBEX_OBJPUSH_SVCLASS_ID:
> +	case OBEX_FILETRANS_SVCLASS_ID:
> +	case IRMC_SYNC_CMD_SVCLASS_ID:
> +	case PBAP_PSE_SVCLASS_ID:
> +		return 0x10;    /* Object Transfer */
> +	case HEADSET_SVCLASS_ID:
> +	case HANDSFREE_SVCLASS_ID:
> +		return 0x20;    /* Audio */
> +	case CORDLESS_TELEPHONY_SVCLASS_ID:
> +	case INTERCOM_SVCLASS_ID:
> +	case FAX_SVCLASS_ID:
> +	case SAP_SVCLASS_ID:
> +	/*
> +	* Setting the telephony bit for the handsfree audio gateway
> +	* role is not required by the HFP specification, but the
> +	* Nokia 616 carkit is just plain broken! It will refuse
> +	* pairing without this bit set.
> +	*/
> +	case HANDSFREE_AGW_SVCLASS_ID:
> +		return 0x40;    /* Telephony */
> +	case AUDIO_SOURCE_SVCLASS_ID:
> +	case VIDEO_SOURCE_SVCLASS_ID:
> +		return 0x08;    /* Capturing */
> +	case AUDIO_SINK_SVCLASS_ID:
> +	case VIDEO_SINK_SVCLASS_ID:
> +		return 0x04;    /* Rendering */
> +	case PANU_SVCLASS_ID:
> +	case NAP_SVCLASS_ID:
> +	case GN_SVCLASS_ID:
> +		return 0x02;    /* Networking */
> +	default:
> +		return 0;
> +	}
> +}

I don't think it makes sense to duplicate this code in bluez.git,
especially not the last function. Instead, I think it should be
refactored to the appropriate common place (lib/sdp.c maybe? Or maybe
not if we don't want to pollute the already deprecated libbluetooth - in
which case I'd expect a proposal where to put this).

> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
> +{
> +	struct mgmt_cp_add_uuid cp;
> +	uuid_t uuid128;
> +	uint128_t uint128;
> +
> +	uuid_to_uuid128(&uuid128, uuid);
> +
> +	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> +	htob128(&uint128, (uint128_t *) cp.uuid);
> +	cp.svc_hint = svc_hint;
> +
> +	if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
> +			0, sizeof(cp), &cp,
> +			add_uuid_complete, adapter, NULL) > 0)
> +		return 0;

Since you're skipping the "is_supported_uuid" check that we're doing in
the normal bluetoothd I suppose we at least have a proper check for a
minimum mgmt version when initializing the android bluetoothd? Otherwise
your patch is broken.

Johan

^ permalink raw reply

* Re: [PATCH] android/client: Add clear screen on Cltr-L
From: Johan Hedberg @ 2013-10-28 12:58 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <1382964493-20202-1-git-send-email-jerzy.kasenberg@tieto.com>

Hi Jerzy,

On Mon, Oct 28, 2013, Jerzy Kasenberg wrote:
> This patch allows to clear screen on Ctrl-L.
> ---
>  android/client/terminal.c |   13 +++++++++++++
>  1 file changed, 13 insertions(+)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] android/client: Add clear screen on Cltr-L
From: Jerzy Kasenberg @ 2013-10-28 12:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg

This patch allows to clear screen on Ctrl-L.
---
 android/client/terminal.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/android/client/terminal.c b/android/client/terminal.c
index 88c963b..e721160 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -94,6 +94,7 @@ static const struct ansii_sequence ansii_sequnces[] = {
 #define KEY_SEQUNCE_NOT_FINISHED -1
 #define KEY_C_C 3
 #define KEY_C_D 4
+#define KEY_C_L 12
 
 #define isseqence(c) ((c) == 0x1B)
 
@@ -237,6 +238,15 @@ static void terminal_clear_line(void)
 	terminal_line_replaced();
 }
 
+static void terminal_clear_sceen(void)
+{
+	line_buf[0] = '\0';
+	line_buf_ix = 0;
+	line_len = 0;
+
+	printf("\x1b[2J\x1b[1;1H%s", prompt);
+}
+
 static void terminal_delete_char(void)
 {
 	/* delete character under cursor if not at the very end */
@@ -525,6 +535,9 @@ void terminal_process_char(int c, void (*process_line)(char *line))
 			exit(0);
 		}
 		break;
+	case KEY_C_L:
+		terminal_clear_sceen();
+		break;
 	default:
 		if (!isprint(c)) {
 			/*
-- 
1.7.9.5


^ permalink raw reply related


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