Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] pbap: Fix PhonebookSize endianness
From: Hannu Mallat @ 2014-02-03  7:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Hannu Mallat

As g_obex_apparam_set_uint16() converts data to big-endian format
internally, do not call htons() prior to it.
---
 obexd/plugins/pbap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index 4740188..acac3aa 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
@@ -188,7 +188,7 @@ static void phonebook_size_result(const char *buffer, size_t bufsize,
 
 	DBG("vcards %d", vcards);
 
-	phonebooksize = htons(vcards);
+	phonebooksize = vcards;
 
 	pbap->obj->apparam = g_obex_apparam_set_uint16(NULL, PHONEBOOKSIZE_TAG,
 								phonebooksize);
@@ -365,7 +365,7 @@ static int generate_response(void *user_data)
 
 	if (max == 0) {
 		/* Ignore all other parameter and return PhoneBookSize */
-		uint16_t size = htons(g_slist_length(pbap->cache.entries));
+		uint16_t size = g_slist_length(pbap->cache.entries);
 
 		pbap->obj->apparam = g_obex_apparam_set_uint16(
 							pbap->obj->apparam,
-- 
1.8.5.3


^ permalink raw reply related

* AVRCP profile/plugin in bluez 5
From: Serkan Kaba @ 2014-02-03  6:52 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi,

I was trying to get my GTK-N1BT hi-fi system. It was constantly bailing "UUIDs has unsupported type" errors and disconnecting after the pairing. All the online examples were referring to bluez 4 config (audio.conf) which even in 4 it was hard to get it working. I added the following in "General" section of audio.conf
<code>
Enable=Media,Sink,Source

</code>
and got it working

I couldn't figure out enabling avrcp profile with bluez 5. Please help

^ permalink raw reply

* [PATCH 13/13] android/handsfree: Add support for AT+CMER command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/android/handsfree.c b/android/handsfree.c
index 02135cb..bf6a575 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -63,6 +63,7 @@ static struct {
 	struct hfp_gw *gw;
 
 	uint32_t features;
+	bool ind_notif_active;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -172,6 +173,30 @@ static bool at_cind(const char *at)
 	return false;
 }
 
+static bool at_cmer(const char *at)
+{
+	unsigned int mode, ind;
+	int ret;
+
+	DBG("");
+
+	ret = sscanf(at, " = %u, %*u, %*u, %u", &mode, &ind);
+	if (ret != 2 || mode != 3 || ind > 1) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+		return false;
+	}
+
+	device.ind_notif_active = ind;
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+	/* TODO Check for 3-way calling support */
+	device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED);
+
+	return true;
+}
+
 static const struct {
 	const char *prefix;
 	int prefix_len;
@@ -179,6 +204,7 @@ static const struct {
 } at_cmds[] = {
 	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
 	{ "+CIND", sizeof("+CIND") - 1, at_cind },
+	{ "+CMER", sizeof("+CMER") - 1, at_cmer },
 };
 
 static void at_command_handler(const char *command, void *user_data)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 12/13] android/handsfree: Add support for AT+CIND command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

Android supports only fixed number of indicators so this is all static
for now.
---
 android/handsfree.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 990ba2f..02135cb 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -51,6 +51,10 @@
 
 #define AG_FEATURES 0
 
+#define CIND_SUPPORT_STR "+CIND: (\"service\",(0,1)),(\"call\",(0,1)),\
+			(\"callsetup\",(0-3)),(\"callheld\",(0-2)),\
+			(\"signal\",(0-5)),(\"roam\",(0,1)),(\"battchg\",(0,1))"
+
 static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
@@ -146,12 +150,35 @@ static bool at_brsf(const char *at)
 	return true;
 }
 
+static bool at_cind(const char *at)
+{
+	if (strcmp(at, "?")) {
+		ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CIND,
+								0, NULL);
+
+		return true;
+	}
+
+	if (strcmp(at, "=?")) {
+		hfp_gw_send_info(device.gw, "%s", CIND_SUPPORT_STR);
+
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return true;
+	}
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+	return false;
+}
+
 static const struct {
 	const char *prefix;
 	int prefix_len;
 	bool (*func)(const char *at_cmds);
 } at_cmds[] = {
 	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+	{ "+CIND", sizeof("+CIND") - 1, at_cind },
 };
 
 static void at_command_handler(const char *command, void *user_data)
@@ -466,12 +493,41 @@ static void handle_cops(const void *buf, uint16_t len)
 							HAL_STATUS_FAILED);
 }
 
+static unsigned int get_callsetup(uint8_t state)
+{
+	switch (state) {
+	case HAL_HANDSFREE_CALL_STATE_INCOMING:
+		return 1;
+	case HAL_HANDSFREE_CALL_STATE_DIALING:
+		return 2;
+	case HAL_HANDSFREE_CALL_STATE_ALERTING:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
 static void handle_cind(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_cind_response *cmd = buf;
+
 	DBG("");
 
+	/* HAL doesn't provide CIND values directly so need to convert here */
+
+	hfp_gw_send_info(device.gw, "+CIND: %u,%u,%u,%u,%u,%u,%u",
+				cmd->svc,
+				!!(cmd->num_active + cmd->num_held),
+				get_callsetup(cmd->state),
+				cmd->num_held ? (cmd->num_active ? 1 : 2) : 0,
+				cmd->signal,
+				cmd->roam,
+				cmd->batt_chg);
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
-							HAL_STATUS_FAILED);
+							HAL_STATUS_SUCCESS);
 }
 
 static void handle_formatted_at_resp(const void *buf, uint16_t len)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 11/13] android/handsfree: Add AT+BRSF command support
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 5fe7638..990ba2f 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -49,12 +49,16 @@
 #define HFP_AG_CHANNEL 13
 #define HFP_AG_FEATURES 0
 
+#define AG_FEATURES 0
+
 static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
 	GIOChannel *io;
 	guint watch;
 	struct hfp_gw *gw;
+
+	uint32_t features;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -123,11 +127,69 @@ static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
 	return FALSE;
 }
 
+static bool at_brsf(const char *at)
+{
+	uint32_t feat;
+
+	if (sscanf(at, " = %u", &feat) != 1) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+		return false;
+	}
+
+	/* TODO verify features */
+	device.features = feat;
+
+	hfp_gw_send_info(device.gw, "+BRSF=%u", AG_FEATURES);
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+	return true;
+}
+
+static const struct {
+	const char *prefix;
+	int prefix_len;
+	bool (*func)(const char *at_cmds);
+} at_cmds[] = {
+	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+};
+
 static void at_command_handler(const char *command, void *user_data)
 {
+	unsigned int i;
+
+	if (strlen(command) < 3)
+		goto error;
+
+	if (strncmp(command, "AT", sizeof("AT") - 1))
+		goto error;
+
+	command += sizeof("AT") - 1;
+
+	for (i = 0; i < G_N_ELEMENTS(at_cmds); i++) {
+		if (strncmp(command, at_cmds[i].prefix, at_cmds[i].prefix_len))
+			continue;
+
+		command += at_cmds[i].prefix_len;
+
+		if (at_cmds[i].func(command))
+			return;
+
+		goto check_slc;
+	}
+
+error:
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 
-	g_io_channel_shutdown(device.io, TRUE, NULL);
+check_slc:
+	/* Error while establishing SLC */
+	if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED)
+		g_io_channel_shutdown(device.io, TRUE, NULL);
+}
+
+static void hfp_gw_debug(const char *str, void *user_data)
+{
+	DBG("%s", str);
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -148,6 +210,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	hfp_gw_set_close_on_unref(device.gw, true);
 	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
 
+	hfp_gw_set_debug(device.gw, hfp_gw_debug, NULL, NULL);
+
 	device.watch = g_io_add_watch(chan,
 					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 					watch_cb, NULL);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 10/13] android/handsfree: Add disconnect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 79e61b4..5fe7638 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -311,10 +311,38 @@ failed:
 
 static void handle_disconnect(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_disconnect *cmd = buf;
+	bdaddr_t bdaddr;
+	uint8_t status;
+
 	DBG("");
 
+	android2bdaddr(cmd->bdaddr, &bdaddr);
+
+	if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED ||
+			bacmp(&device.bdaddr, &bdaddr)) {
+		status = HAL_STATUS_FAILED;
+		goto failed;
+
+	}
+
+	if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING) {
+		status = HAL_STATUS_SUCCESS;
+		goto failed;
+	}
+
+	if (device.io) {
+		device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING);
+		g_io_channel_shutdown(device.io, TRUE, NULL);
+	} else {
+		device_cleanup();
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+failed:
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
-							HAL_STATUS_FAILED);
+									status);
 }
 
 static void handle_connect_audio(const void *buf, uint16_t len)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 09/13] android/handsfree: Add connect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This allows to query SDP for RFCOMM channel and connect.
---
 android/handsfree.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 100 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index a4ce398..79e61b4 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -202,12 +202,111 @@ drop:
 	g_io_channel_shutdown(chan, TRUE, NULL);
 }
 
+static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+	sdp_list_t *protos, *classes;
+	GError *gerr = NULL;
+	GIOChannel *io;
+	uuid_t uuid;
+	int channel;
+
+	DBG("");
+
+	if (err < 0) {
+		error("handsfree: unable to get SDP record: %s", strerror(-err));
+		goto fail;
+	}
+
+	if (!recs || !recs->data) {
+		error("handsfree: no SDP records found");
+		goto fail;
+	}
+
+	if (sdp_get_service_classes(recs->data, &classes) < 0) {
+		error("handsfree: unable to get service classes from record");
+		goto fail;
+	}
+
+	if (sdp_get_access_protos(recs->data, &protos) < 0) {
+		error("handsfree: unable to get access protocols from record");
+		goto fail;
+	}
+
+	/* TODO read remote version? */
+
+	memcpy(&uuid, classes->data, sizeof(uuid));
+	sdp_list_free(classes, free);
+
+	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
+			uuid.value.uuid16 != HANDSFREE_SVCLASS_ID) {
+		sdp_list_free(protos, NULL);
+		error("handsfree: invalid service record or not HFP");
+		goto fail;
+	}
+
+	channel = sdp_get_proto_port(protos, RFCOMM_UUID);
+	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
+	sdp_list_free(protos, NULL);
+	if (channel <= 0) {
+		error("handsfree: unable to get RFCOMM channel from record");
+		goto fail;
+	}
+
+	io = bt_io_connect(connect_cb, NULL, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+				BT_IO_OPT_CHANNEL, channel,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("handsfree: unable to connect: %s", gerr->message);
+		g_error_free(gerr);
+		goto fail;
+	}
+
+	g_io_channel_unref(io);
+	return;
+
+fail:
+	device_cleanup();
+}
+
 static void handle_connect(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_connect *cmd = buf;
+	char addr[18];
+	uint8_t status;
+	uuid_t uuid;
+	bdaddr_t bdaddr;
+
 	DBG("");
 
+	if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED) {
+		status = HAL_STATUS_FAILED;
+		goto failed;
+	}
+
+	android2bdaddr(&cmd->bdaddr, &bdaddr);
+
+	ba2str(&device.bdaddr, addr);
+	DBG("connecting to %s", addr);
+
+	device_init(&bdaddr);
+
+	bt_string2uuid(&uuid, HFP_HS_UUID);
+	if (bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
+					sdp_search_cb, NULL, NULL, 0) < 0) {
+		error("handsfree: SDP search failed");
+		device_cleanup();
+		status = HAL_STATUS_FAILED;
+		goto failed;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+failed:
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
-							HAL_STATUS_FAILED);
+									status);
 }
 
 static void handle_disconnect(const void *buf, uint16_t len)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 08/13] android/handsfree: Add initial code for AT commands processing
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

Currently always reply with error and disconnect connection.
---
 android/Makefile.am |  2 ++
 android/handsfree.c | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/android/Makefile.am b/android/Makefile.am
index 23e30c9..41bbbcb 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -27,6 +27,8 @@ android_bluetoothd_SOURCES = android/main.c \
 				src/shared/queue.h src/shared/queue.c \
 				src/shared/util.h src/shared/util.c \
 				src/shared/mgmt.h src/shared/mgmt.c \
+				src/shared/ringbuf.h src/shared/ringbuf.c \
+				src/shared/hfp.h src/shared/hfp.c \
 				android/bluetooth.h android/bluetooth.c \
 				android/hidhost.h android/hidhost.c \
 				android/ipc.h android/ipc.c \
diff --git a/android/handsfree.c b/android/handsfree.c
index ad4c0ff..a4ce398 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -37,6 +37,7 @@
 #include "lib/uuid.h"
 #include "src/sdp-client.h"
 #include "src/uuid-helper.h"
+#include "src/shared/hfp.h"
 #include "btio/btio.h"
 #include "handsfree.h"
 #include "bluetooth.h"
@@ -53,6 +54,7 @@ static struct {
 	uint8_t state;
 	GIOChannel *io;
 	guint watch;
+	struct hfp_gw *gw;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -89,6 +91,11 @@ static void device_init(const bdaddr_t *bdaddr)
 
 static void device_cleanup(void)
 {
+	if (device.gw) {
+		hfp_gw_unref(device.gw);
+		device.gw = NULL;
+	}
+
 	if (device.watch) {
 		g_source_remove(device.watch);
 		device.watch = 0;
@@ -116,6 +123,13 @@ static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
 	return FALSE;
 }
 
+static void at_command_handler(const char *command, void *user_data)
+{
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+	g_io_channel_shutdown(device.io, TRUE, NULL);
+}
+
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
 	DBG("");
@@ -127,6 +141,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 	g_io_channel_set_close_on_unref(chan, TRUE);
 
+	device.gw = hfp_gw_new(g_io_channel_unix_get_fd(chan));
+	if (!device.gw)
+		goto failed;
+
+	hfp_gw_set_close_on_unref(device.gw, true);
+	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
+
 	device.watch = g_io_add_watch(chan,
 					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 					watch_cb, NULL);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 07/13] android/handsfree: Add support for RFCOMM connection handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This adds incoming connection handling and initial connection state
tracking. Only one device is allowed to be connected at the same time.
---
 android/handsfree.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 165 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index d2dc543..ad4c0ff 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -25,24 +25,162 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
 #include <glib.h>
 
 #include "lib/bluetooth.h"
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
+#include "lib/uuid.h"
+#include "src/sdp-client.h"
+#include "src/uuid-helper.h"
+#include "btio/btio.h"
 #include "handsfree.h"
 #include "bluetooth.h"
 #include "src/log.h"
 #include "hal-msg.h"
 #include "ipc.h"
+#include "utils.h"
 
 #define HFP_AG_CHANNEL 13
 #define HFP_AG_FEATURES 0
 
+static struct {
+	bdaddr_t bdaddr;
+	uint8_t state;
+	GIOChannel *io;
+	guint watch;
+} device;
+
 static bdaddr_t adapter_addr;
 static uint32_t record_id = 0;
 
+static GIOChannel *server = NULL;
+
+static void device_set_state(uint8_t state)
+{
+	struct hal_ev_handsfree_conn_state ev;
+	char address[18];
+
+	if (device.state == state)
+		return;
+
+	device.state = state;
+
+	ba2str(&device.bdaddr, address);
+	DBG("device %s state %u", address, state);
+
+	bdaddr2android(&device.bdaddr, ev.bdaddr);
+	ev.state = state;
+
+	ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CONN_STATE,
+							sizeof(ev), &ev);
+}
+
+static void device_init(const bdaddr_t *bdaddr)
+{
+	bacpy(&device.bdaddr, bdaddr);
+
+	device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTING);
+}
+
+static void device_cleanup(void)
+{
+	if (device.watch) {
+		g_source_remove(device.watch);
+		device.watch = 0;
+	}
+
+	if (device.io) {
+		g_io_channel_unref(device.io);
+		device.io = NULL;
+	}
+
+	device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED);
+
+	memset(&device, 0, sizeof(device));
+}
+
+static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
+{
+	DBG("");
+
+	device.watch = 0;
+
+	device_cleanup();
+
+	return FALSE;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+	DBG("");
+
+	if (err) {
+		error("handsfree: connect failed (%s)", err->message);
+		goto failed;
+	}
+
+	g_io_channel_set_close_on_unref(chan, TRUE);
+
+	device.watch = g_io_add_watch(chan,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					watch_cb, NULL);
+	if (device.watch == 0)
+		goto failed;
+
+	device.io = g_io_channel_ref(chan);
+
+	device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTED);
+
+	return;
+
+failed:
+	g_io_channel_shutdown(chan, TRUE, NULL);
+	device_cleanup();
+}
+
+static void confirm_cb(GIOChannel *chan, gpointer data)
+{
+	char address[18];
+	bdaddr_t bdaddr;
+	GError *err = NULL;
+
+	bt_io_get(chan, &err,
+			BT_IO_OPT_DEST, address,
+			BT_IO_OPT_DEST_BDADDR, &bdaddr,
+			BT_IO_OPT_INVALID);
+	if (err) {
+		error("handsfree: confirm failed (%s)", err->message);
+		g_error_free(err);
+		goto drop;
+	}
+
+	DBG("incoming connect from %s", address);
+
+	if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED) {
+		info("handsfree: refusing connection from %s", address);
+		goto drop;
+	}
+
+	device_init(&bdaddr);
+
+	if (!bt_io_accept(chan, connect_cb, NULL, NULL, NULL)) {
+		error("handsfree: failed to accept connection");
+		device_cleanup();
+		goto drop;
+	}
+
+	return;
+
+drop:
+	g_io_channel_shutdown(chan, TRUE, NULL);
+}
+
 static void handle_connect(const void *buf, uint16_t len)
 {
 	DBG("");
@@ -271,21 +409,33 @@ static sdp_record_t *handsfree_ag_record(void)
 bool bt_handsfree_register(const bdaddr_t *addr)
 {
 	sdp_record_t *rec;
+	GError *err = NULL;
 
 	DBG("");
 
 	bacpy(&adapter_addr, addr);
 
+	server =  bt_io_listen( NULL, confirm_cb, NULL, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_CHANNEL, HFP_AG_CHANNEL,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+				BT_IO_OPT_INVALID);
+	if (!server) {
+		error("Failed to listen on Handsfree rfcomm: %s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
 	rec = handsfree_ag_record();
 	if (!rec) {
 		error("Failed to allocate Handsfree record");
-		return false;
+		goto failed;
 	}
 
 	if (bt_adapter_add_record(rec, 0) < 0) {
 		error("Failed to register Handsfree record");
 		sdp_record_free(rec);
-		return false;
+		goto failed;
 	}
 	record_id = rec->handle;
 
@@ -293,6 +443,13 @@ bool bt_handsfree_register(const bdaddr_t *addr)
 						G_N_ELEMENTS(cmd_handlers));
 
 	return true;
+
+failed:
+	g_io_channel_shutdown(server, TRUE, NULL);
+	g_io_channel_unref(server);
+	server = NULL;
+
+	return false;
 }
 
 void bt_handsfree_unregister(void)
@@ -301,6 +458,12 @@ void bt_handsfree_unregister(void)
 
 	ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
 
+	if (server) {
+		g_io_channel_shutdown(server, TRUE, NULL);
+		g_io_channel_unref(server);
+		server = NULL;
+	}
+
 	bt_adapter_remove_record(record_id);
 	record_id = 0;
 }
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 06/13] android/handsfree: Add SDP record for AG
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

Service Name: Hands-Free Audio GatewayService RecHandle: 0x10001
Service Class ID List:
  "Handsfree Audio Gateway" (0x111f)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 13
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0106
---
 android/handsfree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/android/handsfree.c b/android/handsfree.c
index 3c0d52b..d2dc543 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -29,12 +29,19 @@
 #include <glib.h>
 
 #include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
 #include "handsfree.h"
+#include "bluetooth.h"
 #include "src/log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 
+#define HFP_AG_CHANNEL 13
+#define HFP_AG_FEATURES 0
+
 static bdaddr_t adapter_addr;
+static uint32_t record_id = 0;
 
 static void handle_connect(const void *buf, uint16_t len)
 {
@@ -189,12 +196,99 @@ static const struct ipc_handler cmd_handlers[] = {
 			sizeof(struct hal_cmd_handsfree_phone_state_change)},
 };
 
+static sdp_record_t *handsfree_ag_record(void)
+{
+	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
+	uuid_t l2cap_uuid, rfcomm_uuid;
+	sdp_profile_desc_t profile;
+	sdp_list_t *aproto, *proto[2];
+	sdp_record_t *record;
+	sdp_data_t *channel, *features;
+	uint8_t netid = 0x01;
+	uint16_t sdpfeat;
+	sdp_data_t *network;
+	uint8_t ch = HFP_AG_CHANNEL;
+
+	record = sdp_record_alloc();
+	if (!record)
+		return NULL;
+
+	network = sdp_data_alloc(SDP_UINT8, &netid);
+	if (!network) {
+		sdp_record_free(record);
+		return NULL;
+	}
+
+	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+	root = sdp_list_append(0, &root_uuid);
+	sdp_set_browse_groups(record, root);
+
+	sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
+	svclass_id = sdp_list_append(0, &svclass_uuid);
+	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
+	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
+	sdp_set_service_classes(record, svclass_id);
+
+	sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
+	profile.version = 0x0106;
+	pfseq = sdp_list_append(0, &profile);
+	sdp_set_profile_descs(record, pfseq);
+
+	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+	proto[0] = sdp_list_append(0, &l2cap_uuid);
+	apseq = sdp_list_append(0, proto[0]);
+
+	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+	proto[1] = sdp_list_append(0, &rfcomm_uuid);
+	channel = sdp_data_alloc(SDP_UINT8, &ch);
+	proto[1] = sdp_list_append(proto[1], channel);
+	apseq = sdp_list_append(apseq, proto[1]);
+
+	sdpfeat = HFP_AG_FEATURES;
+	features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
+	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+	aproto = sdp_list_append(0, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);
+
+	sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
+
+	sdp_data_free(channel);
+	sdp_list_free(proto[0], 0);
+	sdp_list_free(proto[1], 0);
+	sdp_list_free(apseq, 0);
+	sdp_list_free(pfseq, 0);
+	sdp_list_free(aproto, 0);
+	sdp_list_free(root, 0);
+	sdp_list_free(svclass_id, 0);
+
+	return record;
+}
+
 bool bt_handsfree_register(const bdaddr_t *addr)
 {
+	sdp_record_t *rec;
+
 	DBG("");
 
 	bacpy(&adapter_addr, addr);
 
+	rec = handsfree_ag_record();
+	if (!rec) {
+		error("Failed to allocate Handsfree record");
+		return false;
+	}
+
+	if (bt_adapter_add_record(rec, 0) < 0) {
+		error("Failed to register Handsfree record");
+		sdp_record_free(rec);
+		return false;
+	}
+	record_id = rec->handle;
+
 	ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
 
@@ -206,4 +300,7 @@ void bt_handsfree_unregister(void)
 	DBG("");
 
 	ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+
+	bt_adapter_remove_record(record_id);
+	record_id = 0;
 }
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 05/13] android/hal-handsfree: Implement sending commands
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This implements HAL interface methods and pass commands over IPC.
---
 android/hal-handsfree.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 344 insertions(+)

diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 6e11367..601c14f 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -223,6 +223,336 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
 	return ret;
 }
 
+static bt_status_t handsfree_connect(bt_bdaddr_t *bd_addr)
+{
+	struct hal_cmd_handsfree_connect cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
+{
+	struct hal_cmd_handsfree_disconnect cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_DISCONNECT, sizeof(cmd), &cmd,
+				0, NULL, NULL);
+}
+
+static bt_status_t connect_audio(bt_bdaddr_t *bd_addr)
+{
+	struct hal_cmd_handsfree_connect_audio cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_CONNECT_AUDIO, sizeof(cmd),
+				&cmd, 0, NULL, NULL);
+}
+
+static bt_status_t disconnect_audio(bt_bdaddr_t *bd_addr)
+{
+	struct hal_cmd_handsfree_disconnect_audio cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!bd_addr)
+		return BT_STATUS_PARM_INVALID;
+
+	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_DISCONNECT_AUDIO, sizeof(cmd),
+				&cmd, 0, NULL, NULL);
+}
+
+static bt_status_t start_voice_recognition(void)
+{
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
+							0, NULL, 0, NULL, NULL);
+}
+
+static bt_status_t stop_voice_recognition(void)
+{
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
+							0, NULL, 0, NULL, NULL);
+}
+
+static bt_status_t volume_control(bthf_volume_type_t type, int volume)
+{
+	struct hal_cmd_handsfree_volume_control cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	cmd.type = type;
+	cmd.volume = volume;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_VOLUME_CONTROL, sizeof(cmd),
+				&cmd, 0, NULL, NULL);
+}
+
+static bt_status_t device_status_notification(bthf_network_state_t state,
+						bthf_service_type_t type,
+						int signal, int battery)
+{
+	struct hal_cmd_handsfree_device_status_notif cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	cmd.state = state;
+	cmd.type = type;
+	cmd.signal = signal;
+	cmd.battery = battery;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t cops_response(const char *cops)
+{
+	struct hal_cmd_handsfree_cops_response *cmd;
+	bt_status_t status;
+	int len;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!cops)
+		return BT_STATUS_PARM_INVALID;
+
+	len = sizeof(*cmd) + strlen(cops);
+
+	cmd = malloc(len);
+	if (!cmd)
+		return BT_STATUS_NOMEM;
+
+	cmd->len = strlen(cops);
+	memcpy(cmd->buf, cops, cmd->len);
+
+	status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_COPS_RESPONSE, len, cmd, 0,
+				NULL, NULL);
+
+	free(cmd);
+
+	return status;
+}
+
+static bt_status_t cind_response(int svc, int num_active, int num_held,
+					bthf_call_state_t state, int signal,
+					int roam, int batt_chg)
+{
+	struct hal_cmd_handsfree_cind_response cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	cmd.svc = svc;
+	cmd.num_active = num_active;
+	cmd.num_held = num_held;
+	cmd.state = state;
+	cmd.signal = signal;
+	cmd.roam = roam;
+	cmd.batt_chg = batt_chg;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_CIND_RESPONSE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t formatted_at_response(const char *rsp)
+{
+	struct hal_cmd_handsfree_formatted_at_response *cmd;
+	bt_status_t status;
+	int len;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	if (!rsp)
+		return BT_STATUS_PARM_INVALID;
+
+	len = sizeof(*cmd) + strlen(rsp);
+
+	cmd = malloc(len);
+	if (!cmd)
+		return BT_STATUS_NOMEM;
+
+	cmd->len = strlen(rsp);
+	memcpy(cmd->buf, rsp, cmd->len);
+
+	status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+				HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE, len,
+				cmd, 0, NULL, NULL);
+
+	free(cmd);
+
+	return status;
+}
+
+static bt_status_t at_response(bthf_at_response_t response, int error)
+{
+	struct hal_cmd_handsfree_at_response cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	cmd.response = response;
+	cmd.error = error;
+
+	return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_AT_RESPONSE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+}
+
+static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
+					bthf_call_state_t state,
+					bthf_call_mode_t mode,
+					bthf_call_mpty_type_t mpty,
+					const char *number,
+					bthf_call_addrtype_t type)
+{
+	struct hal_cmd_handsfree_clcc_response *cmd;
+	bt_status_t status;
+	int len;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	len = sizeof(*cmd);
+	if (number)
+		len += strlen(number);
+
+	cmd = malloc(len);
+	if (!cmd)
+		return BT_STATUS_NOMEM;
+
+	cmd->index = index;
+	cmd->dir = dir;
+	cmd->state = state;
+	cmd->mode = mode;
+	cmd->mpty = mpty;
+	cmd->type = type;
+
+	if (number) {
+		cmd->number_len = strlen(number);
+		memcpy(cmd->number, number, cmd->number_len);
+	} else {
+		cmd->number_len = 0;
+	}
+
+	status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_CLCC_RESPONSE, len,
+					cmd, 0, NULL, NULL);
+
+	free(cmd);
+
+	return status;
+}
+
+static bt_status_t phone_state_change(int num_active, int num_held,
+					bthf_call_state_t state,
+					const char *number,
+					bthf_call_addrtype_t type)
+{
+	struct hal_cmd_handsfree_phone_state_change *cmd;
+	bt_status_t status;
+	int len;
+
+	DBG("");
+
+	if (!interface_ready())
+		return BT_STATUS_NOT_READY;
+
+	len = sizeof(*cmd);
+	if (number)
+		len += strlen(number);
+
+	cmd = malloc(len);
+	if (!cmd)
+		return BT_STATUS_NOMEM;
+
+	cmd->num_active = num_active;
+	cmd->num_held = num_held;
+	cmd->state = state;
+	cmd->type = type;
+
+	if (number) {
+		cmd->number_len = strlen(number);
+		memcpy(cmd->number, number, cmd->number_len);
+	} else {
+		cmd->number_len = 0;
+	}
+
+	status = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
+					len, cmd, 0, NULL, NULL);
+
+	free(cmd);
+
+	return status;
+}
+
 static void cleanup(void)
 {
 	struct hal_cmd_unregister_module cmd;
@@ -245,6 +575,20 @@ static void cleanup(void)
 static bthf_interface_t iface = {
 	.size = sizeof(iface),
 	.init = init,
+	.connect = handsfree_connect,
+	.disconnect = disconnect,
+	.connect_audio = connect_audio,
+	.disconnect_audio = disconnect_audio,
+	.start_voice_recognition = start_voice_recognition,
+	.stop_voice_recognition = stop_voice_recognition,
+	.volume_control = volume_control,
+	.device_status_notification = device_status_notification,
+	.cops_response = cops_response,
+	.cind_response = cind_response,
+	.formatted_at_response = formatted_at_response,
+	.at_response = at_response,
+	.clcc_response = clcc_response,
+	.phone_state_change = phone_state_change,
 	.cleanup = cleanup
 };
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 04/13] android/hal-handsfree: Implement notifications handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This implements all notifications handlers and call proper HAL
callbacks.
---
 android/hal-handsfree.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 159 insertions(+), 1 deletion(-)

diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 181e05f..6e11367 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -18,6 +18,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "hal-log.h"
 #include "hal.h"
@@ -31,10 +32,167 @@ static bool interface_ready(void)
 	return cbs != NULL;
 }
 
+static void handle_conn_state(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_conn_state *ev = buf;
+
+	if (cbs->connection_state_cb)
+		cbs->connection_state_cb(ev->state,
+						(bt_bdaddr_t *) (ev->bdaddr));
+}
+
+static void handle_audio_state(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_audio_state *ev = buf;
+
+	if (cbs->audio_state_cb)
+		cbs->audio_state_cb(ev->state, (bt_bdaddr_t *) (ev->bdaddr));
+}
+
+static void handle_vr_state(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_vr_state *ev = buf;
+
+	if (cbs->vr_cmd_cb)
+		cbs->vr_cmd_cb(ev->state);
+}
+
+static void handle_answer(void *buf, uint16_t len)
+{
+	if (cbs->answer_call_cmd_cb)
+		cbs->answer_call_cmd_cb();
+}
+
+static void handle_hangup(void *buf, uint16_t len)
+{
+	if (cbs->hangup_call_cmd_cb)
+		cbs->hangup_call_cmd_cb();
+}
+
+static void handle_volume(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_volume *ev = buf;
+
+	if (cbs->volume_cmd_cb)
+		cbs->volume_cmd_cb(ev->type, ev->volume);
+}
+
+static void handle_dial(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_dial *ev = buf;
+
+	if (len != sizeof(*ev) + ev->number_len) {
+		error("invalid dial event, aborting");
+		exit(EXIT_FAILURE);
+	}
+
+	if (cbs->dial_call_cmd_cb)
+		cbs->dial_call_cmd_cb((char *) ev->number);
+}
+
+static void handle_dtmf(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_dtmf *ev = buf;
+
+	if (cbs->dtmf_cmd_cb)
+		cbs->dtmf_cmd_cb(ev->tone);
+}
+
+static void handle_nrec(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_nrec *ev = buf;
+
+	if (cbs->nrec_cmd_cb)
+		cbs->nrec_cmd_cb(ev->nrec);
+}
+
+static void handle_chld(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_chld *ev = buf;
+
+	if (cbs->chld_cmd_cb)
+		cbs->chld_cmd_cb(ev->chld);
+}
+
+static void handle_cnum(void *buf, uint16_t len)
+{
+	if (cbs->cnum_cmd_cb)
+		cbs->cnum_cmd_cb();
+}
+
+static void handle_cind(void *buf, uint16_t len)
+{
+	if (cbs->cind_cmd_cb)
+		cbs->cind_cmd_cb();
+}
+
+static void handle_cops(void *buf, uint16_t len)
+{
+	if (cbs->cops_cmd_cb)
+		cbs->cops_cmd_cb();
+}
+
+static void handle_clcc(void *buf, uint16_t len)
+{
+	if (cbs->clcc_cmd_cb)
+		cbs->clcc_cmd_cb();
+}
+
+static void handle_unknown_at(void *buf, uint16_t len)
+{
+	struct hal_ev_handsfree_unknown_at *ev = buf;
+
+	if (len != sizeof(*ev) + ev->len) {
+		error("invalid dial event, aborting");
+		exit(EXIT_FAILURE);
+	}
+
+	if (cbs->unknown_at_cmd_cb)
+		cbs->unknown_at_cmd_cb((char *) ev->buf);
+}
+
+static void handle_hsp_key_press(void *buf, uint16_t len)
+{
+	if (cbs->key_pressed_cmd_cb)
+		cbs->key_pressed_cmd_cb();
+}
+
 /* handlers will be called from notification thread context,
  * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
 static const struct hal_ipc_handler ev_handlers[] = {
-
+	/* HAL_EV_HANDSFREE_CONN_STATE */
+	{handle_conn_state, false, sizeof(struct hal_ev_handsfree_conn_state)},
+	/* HAL_EV_HANDSFREE_AUDIO_STATE */
+	{handle_audio_state, false,
+				sizeof(struct hal_ev_handsfree_audio_state)},
+	/* HAL_EV_HANDSFREE_VR */
+	{handle_vr_state, false, sizeof(struct hal_ev_handsfree_vr_state)},
+	/*HAL_EV_HANDSFREE_ANSWER */
+	{handle_answer, false, 0},
+	/*HAL_EV_HANDSFREE_HANGUP */
+	{handle_hangup, false, 0},
+	/* HAL_EV_HANDSFREE_VOLUME */
+	{handle_volume, false, sizeof(struct hal_ev_handsfree_volume)},
+	/* HAL_EV_HANDSFREE_DIAL */
+	{handle_dial, true, sizeof(struct hal_ev_handsfree_dial)},
+	/* HAL_EV_HANDSFREE_DTMF */
+	{handle_dtmf, false, sizeof(struct hal_ev_handsfree_dtmf)},
+	/* HAL_EV_HANDSFREE_NREC */
+	{handle_nrec, false, sizeof(struct hal_ev_handsfree_nrec)},
+	/* HAL_EV_HANDSFREE_CHLD */
+	{handle_chld, false, sizeof(struct hal_ev_handsfree_chld)},
+	/* HAL_EV_HANDSFREE_CNUM */
+	{handle_cnum, false, 0},
+	/* HAL_EV_HANDSFREE_CIND */
+	{handle_cind, false, 0},
+	/* HAL_EV_HANDSFREE_COPS */
+	{handle_cops, false, 0},
+	/* HAL_EV_HANDSFREE_CLCC */
+	{handle_clcc, false, 0},
+	/* HAL_EV_HANDSFREE_UNKNOWN_AT */
+	{handle_unknown_at, true, sizeof(struct hal_ev_handsfree_unknown_at)},
+	/* HAL_EV_HANDSFREE_HSP_KEY_PRESS */
+	{handle_hsp_key_press, false, 0},
 };
 
 static bt_status_t init(bthf_callbacks_t *callbacks)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 03/13] android/handsfree: Add stubs for commands handlers
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

Add empty handlers for all IPC commands.
---
 android/handsfree.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 169 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index fb48ff1..3c0d52b 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -26,16 +26,184 @@
 #endif
 
 #include <stdbool.h>
+#include <glib.h>
 
 #include "lib/bluetooth.h"
 #include "handsfree.h"
+#include "src/log.h"
+#include "hal-msg.h"
+#include "ipc.h"
+
+static bdaddr_t adapter_addr;
+
+static void handle_connect(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_disconnect(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_connect_audio(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT_AUDIO,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_disconnect_audio(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+			HAL_OP_HANDSFREE_DISCONNECT_AUDIO, HAL_STATUS_FAILED);
+}
+
+static void handle_start_vr(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_stop_vr(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_volume_control(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_VOLUME_CONTROL,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_device_status_notif(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
+					HAL_STATUS_FAILED);
+}
+
+static void handle_cops(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_COPS_RESPONSE,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_cind(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_formatted_at_resp(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
+					HAL_STATUS_FAILED);
+}
+
+static void handle_at_resp(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_AT_RESPONSE,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_clcc_resp(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CLCC_RESPONSE,
+							HAL_STATUS_FAILED);
+}
+
+static void handle_phone_state_change(const void *buf, uint16_t len)
+{
+	DBG("");
+
+	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
+					HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
+					HAL_STATUS_FAILED);
+}
+
+static const struct ipc_handler cmd_handlers[] = {
+	/* HAL_OP_HANDSFREE_CONNECT */
+	{ handle_connect, false, sizeof(struct hal_cmd_handsfree_connect)},
+	/* HAL_OP_HANDSFREE_DISCONNECT */
+	{handle_disconnect, false, sizeof(struct hal_cmd_handsfree_disconnect)},
+	/*HAL_OP_HANDSFREE_CONNECT_AUDIO*/
+	{handle_connect_audio, false,
+			sizeof(struct hal_cmd_handsfree_connect_audio)},
+	/*HAL_OP_HANDSFREE_DISCONNECT_AUDIO*/
+	{handle_disconnect_audio, false,
+			sizeof(struct hal_cmd_handsfree_disconnect_audio)},
+	/* define HAL_OP_HANDSFREE_START_VR */
+	{handle_start_vr, false, 0 },
+	/* define HAL_OP_HANDSFREE_STOP_VR */
+	{handle_stop_vr, false, 0 },
+	/* HAL_OP_HANDSFREE_VOLUME_CONTROL */
+	{handle_volume_control, false,
+			sizeof(struct hal_cmd_handsfree_volume_control)},
+	/* HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF */
+	{handle_device_status_notif, false,
+			sizeof(struct hal_cmd_handsfree_device_status_notif)},
+	/* HAL_OP_HANDSFREE_COPS_RESPONSE */
+	{handle_cops, true, sizeof(struct hal_cmd_handsfree_cops_response)},
+	/* HAL_OP_HANDSFREE_CIND_RESPONSE */
+	{ handle_cind, false, sizeof(struct hal_cmd_handsfree_cind_response)},
+	/* HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE */
+	{handle_formatted_at_resp, true,
+			sizeof(struct hal_cmd_handsfree_formatted_at_response)},
+	/* HAL_OP_HANDSFREE_AT_RESPONSE */
+	{handle_at_resp, false, sizeof(struct hal_cmd_handsfree_at_response)},
+	/* HAL_OP_HANDSFREE_CLCC_RESPONSE */
+	{handle_clcc_resp, true,
+			sizeof(struct hal_cmd_handsfree_clcc_response)},
+	/* HAL_OP_HANDSFREE_PHONE_STATE_CHANGE */
+	{handle_phone_state_change, true,
+			sizeof(struct hal_cmd_handsfree_phone_state_change)},
+};
 
 bool bt_handsfree_register(const bdaddr_t *addr)
 {
-	return false;
+	DBG("");
+
+	bacpy(&adapter_addr, addr);
+
+	ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
+						G_N_ELEMENTS(cmd_handlers));
+
+	return true;
 }
 
 void bt_handsfree_unregister(void)
 {
+	DBG("");
 
+	ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
 }
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 02/13] android/handsfree: Add commands and events definition to IPC header
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/hal-msg.h | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 208 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index d46b428..56e1116 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -389,6 +389,130 @@ struct hal_cmd_pan_disconnect {
 	uint8_t bdaddr[6];
 } __attribute__((packed));
 
+/* Handsfree HAL API */
+
+#define HAL_OP_HANDSFREE_CONNECT		0x01
+struct hal_cmd_handsfree_connect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_DISCONNECT		0x02
+struct hal_cmd_handsfree_disconnect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_CONNECT_AUDIO		0x03
+struct hal_cmd_handsfree_connect_audio {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_DISCONNECT_AUDIO	0x04
+struct hal_cmd_handsfree_disconnect_audio {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_START_VR		0x05
+
+#define HAL_OP_HANDSFREE_STOP_VR		0x06
+
+#define HAL_HANDSFREE_VOLUME_TYPE_SPEAKER	0x00
+#define HAL_HANDSFREE_VOLUME_TYPE_MIC		0x01
+
+#define HAL_OP_HANDSFREE_VOLUME_CONTROL		0x07
+struct hal_cmd_handsfree_volume_control {
+	uint8_t type;
+	uint32_t volume;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_NETWORK_STATE_NOT_AVAILABLE	0x00
+#define HAL_HANDSFREE_NETWORK_STATE_AVAILABLE		0x01
+
+#define HAL_HANDSFREE_SERVICE_TYPE_HOME		0x00
+#define HAL_HANDSFREE_SERVICE_TYPE_ROAMING	0x01
+
+#define HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF	0x08
+struct hal_cmd_handsfree_device_status_notif {
+	uint8_t state;
+	uint8_t type;
+	uint32_t signal;
+	uint32_t battery;
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_COPS_RESPONSE		0x09
+struct hal_cmd_handsfree_cops_response {
+	uint32_t len;
+	uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CALL_STATE_ACTIVE		0x00
+#define HAL_HANDSFREE_CALL_STATE_HELD		0x01
+#define HAL_HANDSFREE_CALL_STATE_DIALING	0x02
+#define HAL_HANDSFREE_CALL_STATE_ALERTING	0x03
+#define HAL_HANDSFREE_CALL_STATE_INCOMING	0x04
+#define HAL_HANDSFREE_CALL_STATE_WAITING	0x05
+#define HAL_HANDSFREE_CALL_STATE_IDLE		0x06
+
+#define HAL_OP_HANDSFREE_CIND_RESPONSE		0x0A
+struct hal_cmd_handsfree_cind_response {
+	uint32_t svc;
+	uint32_t num_active;
+	uint32_t num_held;
+	uint8_t state;
+	uint32_t signal;
+	uint32_t roam;
+	uint32_t batt_chg;
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE	0x0B
+struct hal_cmd_handsfree_formatted_at_response {
+	uint32_t len;
+	uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_AT_RESPONSE_ERROR		0x00
+#define HAL_HANDSFREE_AT_RESPONSE_OK		0x01
+
+#define HAL_OP_HANDSFREE_AT_RESPONSE		0x0C
+struct hal_cmd_handsfree_at_response {
+	uint8_t response;
+	uint32_t error;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CALL_DIRECTION_OUTGOING	0x00
+#define HAL_HANDSFREE_CALL_DIRECTION_INCOMING	0x01
+
+#define HAL_HANDSFREE_CALL_TYPE_VOICE		0x00
+#define HAL_HANDSFREE_CALL_TYPE_DATA		0x01
+#define HAL_HANDSFREE_CALL_TYPE_FAX		0x02
+
+#define HAL_HANDSFREE_CALL_MPTY_TYPE_SINGLE	0x00
+#define HAL_HANDSFREE_CALL_MPTY_TYPE_MULTI	0x01
+
+#define HAL_HANDSFREE_CALL_ADDRTYPE_UNKNOWN	0x81
+#define HAL_HANDSFREE_CALL_ADDRTYPE_INTERNATIONAL	0x91
+
+#define HAL_OP_HANDSFREE_CLCC_RESPONSE		0x0D
+struct hal_cmd_handsfree_clcc_response {
+	uint32_t index;
+	uint8_t dir;
+	uint8_t state;
+	uint8_t mode;
+	uint8_t mpty;
+	uint8_t type;
+	uint32_t number_len;
+	uint8_t number[0];
+} __attribute__((packed));
+
+#define HAL_OP_HANDSFREE_PHONE_STATE_CHANGE	0x0E
+struct hal_cmd_handsfree_phone_state_change {
+	uint32_t num_active;
+	uint32_t num_held;
+	uint8_t state;
+	uint8_t type;
+	uint32_t number_len;
+	uint8_t number[0];
+} __attribute__((packed));
+
 /* Notifications and confirmations */
 
 #define HAL_POWER_OFF			0x00
@@ -572,3 +696,87 @@ struct hal_ev_a2dp_audio_state {
 	uint8_t state;
 	uint8_t bdaddr[6];
 } __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED	0x00
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTING	0x01
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_CONNECTED	0x02
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED	0x03
+#define HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING	0x04
+
+#define HAL_EV_HANDSFREE_CONN_STATE		0x81
+struct hal_ev_handsfree_conn_state {
+	uint8_t state;
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED	0x00
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING		0x01
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED		0x02
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTING	0x03
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE		0x82
+struct hal_ev_handsfree_audio_state {
+	uint8_t state;
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_VR		0x83
+struct hal_ev_handsfree_vr_state {
+	uint8_t state;
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_ANSWER		0x84
+
+#define HAL_EV_HANDSFREE_HANGUP		0x85
+
+#define HAL_EV_HANDSFREE_VOLUME		0x86
+struct hal_ev_handsfree_volume {
+	uint8_t type;
+	uint32_t volume;
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_DIAL		0x87
+struct hal_ev_handsfree_dial {
+	uint32_t number_len;
+	uint8_t number[0];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_DTMF		0x88
+struct hal_ev_handsfree_dtmf {
+	uint8_t tone;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_NREC_STOP		0x00
+#define HAL_HANDSFREE_NREC_STart	0x01
+
+#define HAL_EV_HANDSFREE_NREC		0x89
+struct hal_ev_handsfree_nrec {
+	uint8_t nrec;
+} __attribute__((packed));
+
+#define HAL_HANDSFREE_CHLD_TYPE_RELEASEHELD			0x00
+#define HAL_HANDSFREE_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD	0x01
+#define HAL_HANDSFREE_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD		0x02
+#define HAL_HANDSFREE_CHLD_TYPE_ADDHELDTOCONF			0x03
+
+#define HAL_EV_HANDSFREE_CHLD		0x8A
+struct hal_ev_handsfree_chld {
+	uint8_t chld;
+} __attribute__((packed));
+
+
+#define HAL_EV_HANDSFREE_CNUM		0x8B
+
+#define HAL_EV_HANDSFREE_CIND		0x8C
+
+#define HAL_EV_HANDSFREE_COPS		0x8D
+
+#define HAL_EV_HANDSFREE_CLCC		0x8E
+
+#define HAL_EV_HANDSFREE_UNKNOWN_AT	0x8F
+struct hal_ev_handsfree_unknown_at {
+	uint32_t len;
+	uint8_t buf[0];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_HSP_KEY_PRESS	0x90
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 01/13] android/handsfree: Add initial files
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This adds initial HAL and daemon code for Handsfree profile.
---
 android/Android.mk      |  2 ++
 android/Makefile.am     |  2 ++
 android/hal-bluetooth.c |  3 ++
 android/hal-handsfree.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++
 android/hal.h           |  2 ++
 android/handsfree.c     | 41 +++++++++++++++++++++
 android/handsfree.h     | 25 +++++++++++++
 android/main.c          | 14 ++++++++
 8 files changed, 185 insertions(+)
 create mode 100644 android/hal-handsfree.c
 create mode 100644 android/handsfree.c
 create mode 100644 android/handsfree.h

diff --git a/android/Android.mk b/android/Android.mk
index 03f2d8b..c16f29a 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -32,6 +32,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/avctp.c \
 	bluez/android/avrcp.c \
 	bluez/android/pan.c \
+	bluez/android/handsfree.c \
 	bluez/src/log.c \
 	bluez/src/shared/mgmt.c \
 	bluez/src/shared/util.c \
@@ -108,6 +109,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/hal-pan.c \
 	bluez/android/hal-a2dp.c \
 	bluez/android/hal-avrcp.c \
+	bluez/android/hal-handsfree.c \
 	bluez/android/hal-utils.c \
 
 LOCAL_C_INCLUDES += \
diff --git a/android/Makefile.am b/android/Makefile.am
index e065c0c..23e30c9 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -37,6 +37,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/avrcp.h android/avrcp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
+				android/handsfree.h android/handsfree.c \
 				btio/btio.h btio/btio.c \
 				src/sdp-client.h src/sdp-client.c \
 				profiles/network/bnep.h profiles/network/bnep.c
@@ -51,6 +52,7 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hal-pan.c \
 					android/hal-a2dp.c \
 					android/hal-avrcp.c \
+					android/hal-handsfree.c \
 					android/hardware/bluetooth.h \
 					android/hardware/bt_av.h \
 					android/hardware/bt_gatt.h \
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 0dac158..67c91e4 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -765,6 +765,9 @@ static const void *get_profile_interface(const char *profile_id)
 	if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
 		return bt_get_avrcp_interface();
 
+	if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_ID))
+		return bt_get_handsfree_interface();
+
 	return NULL;
 }
 
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
new file mode 100644
index 0000000..181e05f
--- /dev/null
+++ b/android/hal-handsfree.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "hal-log.h"
+#include "hal.h"
+#include "hal-msg.h"
+#include "hal-ipc.h"
+
+static const bthf_callbacks_t *cbs = NULL;
+
+static bool interface_ready(void)
+{
+	return cbs != NULL;
+}
+
+/* handlers will be called from notification thread context,
+ * index in table equals to 'opcode - HAL_MINIMUM_EVENT' */
+static const struct hal_ipc_handler ev_handlers[] = {
+
+};
+
+static bt_status_t init(bthf_callbacks_t *callbacks)
+{
+	struct hal_cmd_register_module cmd;
+	int ret;
+
+	DBG("");
+
+	if (interface_ready())
+		return BT_STATUS_DONE;
+
+	cbs = callbacks;
+
+	hal_ipc_register(HAL_SERVICE_ID_HANDSFREE, ev_handlers,
+				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
+
+	cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+
+	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+
+	if (ret != BT_STATUS_SUCCESS) {
+		cbs = NULL;
+		hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+	}
+
+	return ret;
+}
+
+static void cleanup(void)
+{
+	struct hal_cmd_unregister_module cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return;
+
+	cbs = NULL;
+
+	cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+
+	hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+
+	hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+}
+
+static bthf_interface_t iface = {
+	.size = sizeof(iface),
+	.init = init,
+	.cleanup = cleanup
+};
+
+bthf_interface_t *bt_get_handsfree_interface(void)
+{
+	return &iface;
+}
diff --git a/android/hal.h b/android/hal.h
index 1ff4fbd..5005b49 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -21,12 +21,14 @@
 #include <hardware/bt_pan.h>
 #include <hardware/bt_av.h>
 #include <hardware/bt_rc.h>
+#include <hardware/bt_hf.h>
 
 btsock_interface_t *bt_get_sock_interface(void);
 bthh_interface_t *bt_get_hidhost_interface(void);
 btpan_interface_t *bt_get_pan_interface(void);
 btav_interface_t *bt_get_a2dp_interface(void);
 btrc_interface_t *bt_get_avrcp_interface(void);
+bthf_interface_t *bt_get_handsfree_interface(void);
 
 void bt_thread_associate(void);
 void bt_thread_disassociate(void);
diff --git a/android/handsfree.c b/android/handsfree.c
new file mode 100644
index 0000000..fb48ff1
--- /dev/null
+++ b/android/handsfree.c
@@ -0,0 +1,41 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+
+#include "lib/bluetooth.h"
+#include "handsfree.h"
+
+bool bt_handsfree_register(const bdaddr_t *addr)
+{
+	return false;
+}
+
+void bt_handsfree_unregister(void)
+{
+
+}
diff --git a/android/handsfree.h b/android/handsfree.h
new file mode 100644
index 0000000..799fcb6
--- /dev/null
+++ b/android/handsfree.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  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
+ *
+ */
+
+bool bt_handsfree_register(const bdaddr_t *addr);
+void bt_handsfree_unregister(void);
diff --git a/android/main.c b/android/main.c
index 417dbc3..d9d0572 100644
--- a/android/main.c
+++ b/android/main.c
@@ -56,6 +56,7 @@
 #include "a2dp.h"
 #include "pan.h"
 #include "avrcp.h"
+#include "handsfree.h"
 
 #define STARTUP_GRACE_SECONDS 5
 #define SHUTDOWN_GRACE_SECONDS 10
@@ -115,6 +116,13 @@ static void service_register(const void *buf, uint16_t len)
 		}
 
 		break;
+	case HAL_SERVICE_ID_HANDSFREE:
+		if (!bt_handsfree_register(&adapter_bdaddr)) {
+			status = HAL_STATUS_FAILED;
+			goto failed;
+		}
+
+		break;
 	default:
 		DBG("service %u not supported", m->service_id);
 		status = HAL_STATUS_FAILED;
@@ -160,6 +168,9 @@ static void service_unregister(const void *buf, uint16_t len)
 	case HAL_SERVICE_ID_AVRCP:
 		bt_avrcp_unregister();
 		break;
+	case HAL_SERVICE_ID_HANDSFREE:
+		bt_handsfree_unregister();
+		break;
 	default:
 		/* This would indicate bug in HAL, as unregister should not be
 		 * called in init failed */
@@ -338,6 +349,9 @@ static void cleanup_services(void)
 		case HAL_SERVICE_ID_PAN:
 			bt_pan_unregister();
 			break;
+		case HAL_SERVICE_ID_HANDSFREE:
+			bt_handsfree_unregister();
+			break;
 		}
 
 		services[i] = false;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 00/13] Initial code for handsfree support
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Hi,

This adds initial support for HFP. HAL library is complete, for daemon
only support for RFCOMM connection handling.

There is also minimal set of AT handling needed for SLC establishment
(proper AT parsing code is still missing).

Comments are welcome.

BR
Szymon Janc

Szymon Janc (13):
  android/handsfree: Add initial files
  android/handsfree: Add commands and events definition to IPC header
  android/handsfree: Add stubs for commands handlers
  android/hal-handsfree: Implement notifications handling
  android/hal-handsfree: Implement sending commands
  android/handsfree: Add SDP record for AG
  android/handsfree: Add support for RFCOMM connection handling
  android/handsfree: Add initial code for AT commands processing
  android/handsfree: Add connect command handling
  android/handsfree: Add disconnect command handling
  android/handsfree: Add AT+BRSF command support
  android/handsfree: Add support for AT+CIND command
  android/handsfree: Add support for AT+CMER command

 android/Android.mk      |   2 +
 android/Makefile.am     |   4 +
 android/hal-bluetooth.c |   3 +
 android/hal-handsfree.c | 598 +++++++++++++++++++++++++++++++++++++
 android/hal-msg.h       | 208 +++++++++++++
 android/hal.h           |   2 +
 android/handsfree.c     | 763 ++++++++++++++++++++++++++++++++++++++++++++++++
 android/handsfree.h     |  25 ++
 android/main.c          |  14 +
 9 files changed, 1619 insertions(+)
 create mode 100644 android/hal-handsfree.c
 create mode 100644 android/handsfree.c
 create mode 100644 android/handsfree.h

-- 
1.8.5.3


^ permalink raw reply

* Re: [PATCH 11/11] android/tester: Make bt_callbacks thread-safe
From: Anderson Lizardo @ 2014-02-02 20:12 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Andrzej Kaczmarek, BlueZ development
In-Reply-To: <EF441CC3-EFCF-4A2A-8ADF-D9F6FF262E4D@holtmann.org>

Hi Marcel,

On Sun, Feb 2, 2014 at 12:55 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> I have to agree. We might better spawn processes for this. Our emulator code was never designed to be thread safe and never will be. We are just hiding the real problem here and it will break somewhere else later on.

One thing I've been experimenting with is to use android/haltest to
"script" the tests. It is not as fine grained as implementing your own
HAL interfaces, but I believe it will allow me to implement most tests
I want (I just started writing the tests).

(BTW, if anyone is doing something similar with haltest, let me know!)

Best Regards,
-- 
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil

^ permalink raw reply

* Re: [PATCH 11/11] android/tester: Make bt_callbacks thread-safe
From: Marcel Holtmann @ 2014-02-02 16:55 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: Andrzej Kaczmarek, BlueZ development
In-Reply-To: <CAJdJm_OCbUjZVEoNL1y7911zk3QgsQKmQjAJfQh15fhLeTGutA@mail.gmail.com>

Hi Anderson,

>> This patch adds wrappers for BT HAL callback which execute them in main
>> thread instead of notification_handler() thread. Otherwise test
>> execution is prone to race conditions since we do not provide any
>> locking mechanism for tester.
> 
> In my opinion, this is becoming too messy. I'm getting races even
> inside the emulator code: sometimes bthost->ncmd becomes zero before a
> HCI command is sent by the emulated host because the Command Status /
> Command Complete comes after the command is written to the socket, but
> before bthost->ncmd is decremented.
> 
> Also try running android-tester under valgrind. At least for me, I get
> a few failures that I don't have when running without valgrind (at
> least one in HIDHost apparently due to if_bluetooth->enable() not
> being called on test setup and thus the tests rely on finishing before
> the controller is powered off by the kernel after initialization).
> 
> IMHO, the best approach would be to keep all HAL API usage in a
> separate process, and keep android-tester single-threaded. Of course,
> this could extra complexity for the required IPC between
> android-tester and this new process...
> 
> Again, I'm not familiar with how HAL API works, all this is just based
> on my failed attempt to make android-tester run reliably under
> valgrind.

I have to agree. We might better spawn processes for this. Our emulator code was never designed to be thread safe and never will be. We are just hiding the real problem here and it will break somewhere else later on.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] android/avrcp: Close AVRCP channel on error
From: Luiz Augusto von Dentz @ 2014-02-02 16:05 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391088223-2586-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Thu, Jan 30, 2014 at 5:23 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> This fixes resource leak.
> ---
>  android/avrcp.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/android/avrcp.c b/android/avrcp.c
> index 485b485..ef833df 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -248,13 +248,13 @@ bool bt_avrcp_register(const bdaddr_t *addr)
>         rec = avrcp_record();
>         if (!rec) {
>                 error("Failed to allocate AVRCP record");
> -               return false;
> +               goto fail;
>         }
>
>         if (bt_adapter_add_record(rec, 0) < 0) {
>                 error("Failed to register AVRCP record");
>                 sdp_record_free(rec);
> -               return false;
> +               goto fail;
>         }
>         record_id = rec->handle;
>
> @@ -262,6 +262,12 @@ bool bt_avrcp_register(const bdaddr_t *addr)
>                                                 G_N_ELEMENTS(cmd_handlers));
>
>         return true;
> +fail:
> +       g_io_channel_shutdown(server, TRUE, NULL);
> +       g_io_channel_unref(server);
> +       server = NULL;
> +
> +       return false;
>  }
>
>  void bt_avrcp_unregister(void)
> --
> 1.8.3.2

Applied, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] gitignore: Add unit/avctp to .gitignore
From: Luiz Augusto von Dentz @ 2014-02-02 16:05 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391092491-21374-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Thu, Jan 30, 2014 at 6:34 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
>  .gitignore | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/.gitignore b/.gitignore
> index e2b23fc..2210e03 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -110,6 +110,7 @@ unit/test-gobex-header
>  unit/test-gobex-packet
>  unit/test-gobex-transfer
>  unit/test-avdtp
> +unit/test-avctp
>  unit/test-*.log
>  unit/test-*.trs
>
> --
> 1.8.3.2

Applied, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] avrcp: Fix wrong pointer check
From: Luiz Augusto von Dentz @ 2014-02-02 16:03 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391157222-24504-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> There is wrong assumption that handler might be NULL while it is a
> pointer to a struct table so check instead for struct members. This
> fixes accessing wrong memory.
> ---
>  profiles/audio/avrcp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index df88138..5030ce1 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
>                         break;
>         }
>
> -       if (!handler || handler->code != *code) {
> +       if (!handler->code || handler->code != *code) {

The code checks if  session->control_handlers is initialized and Im
not sure what is the invalid memory access you are talking about since
handle->code is no a pointer, I do agree that we should probably drop
the second check for the handler in the lines bellow.

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 1/2] avrcp: Fix printing incorrect order for avrcp control header
From: Luiz Augusto von Dentz @ 2014-02-02 15:50 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391171777-27512-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Jan 31, 2014 at 4:36 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
>  profiles/audio/avrcp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index 5030ce1..bc5cab3 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -1658,7 +1658,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
>         }
>
>         DBG("AVRCP PDU 0x%02X, company 0x%06X len 0x%04X",
> -                       pdu->pdu_id, company_id, pdu->params_len);
> +                       pdu->pdu_id, company_id, ntohs(pdu->params_len));
>
>         pdu->packet_type = 0;
>         pdu->rsvd = 0;
> @@ -1755,7 +1755,7 @@ size_t avrcp_handle_vendor_reject(uint8_t *code, uint8_t *operands)
>         pdu->params[0] = AVRCP_STATUS_INTERNAL_ERROR;
>
>         DBG("rejecting AVRCP PDU 0x%02X, company 0x%06X len 0x%04X",
> -                               pdu->pdu_id, company_id, pdu->params_len);
> +                       pdu->pdu_id, company_id, ntohs(pdu->params_len));
>
>         return AVRCP_HEADER_LENGTH + 1;
>  }
> --
> 1.8.3.2

Pushed, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 1/4] android/hal-audio: Check calloc return value
From: Luiz Augusto von Dentz @ 2014-02-02 15:46 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391177929-31416-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Jan 31, 2014 at 6:18 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> calloc() might return NULL and is usually checked for NULL in BlueZ.
> ---
>  android/hal-audio.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index b1323b0..35bafe7 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -313,6 +313,8 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
>         }
>
>         sbc_data = calloc(sizeof(struct sbc_data), 1);
> +       if (!sbc_data)
> +               return AUDIO_STATUS_FAILED;
>
>         memcpy(&sbc_data->sbc, preset->data, preset->len);
>
> --
> 1.8.3.2

Pushed, thanks.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH BlueZ 1/4] audio/player: Fix using invalid end index
From: Luiz Augusto von Dentz @ 2014-02-02 15:40 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391123008-26767-1-git-send-email-luiz.dentz@gmail.com>

Hi,

On Thu, Jan 30, 2014 at 3:03 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> When the End index is not set in ListItems the code automatically pick
> the number of items as end index but the start index start with 0 so
> the correct is to use number of items - 1.
> ---
>  profiles/audio/player.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/profiles/audio/player.c b/profiles/audio/player.c
> index e6d24eb..2bd2d6e 100644
> --- a/profiles/audio/player.c
> +++ b/profiles/audio/player.c
> @@ -808,7 +808,8 @@ static int parse_filters(struct media_player *player, DBusMessageIter *iter,
>         int ctype;
>
>         *start = 0;
> -       *end = folder->number_of_items ? folder->number_of_items : UINT32_MAX;
> +       *end = folder->number_of_items ? folder->number_of_items - 1 :
> +                                                               UINT32_MAX;
>
>         ctype = dbus_message_iter_get_arg_type(iter);
>         if (ctype != DBUS_TYPE_ARRAY)
> --
> 1.8.4.2

Pushed after fixing patch 4/4.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 11/11] android/tester: Make bt_callbacks thread-safe
From: Anderson Lizardo @ 2014-02-02 13:27 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: BlueZ development
In-Reply-To: <1391339801-587-12-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

On Sun, Feb 2, 2014 at 7:16 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> This patch adds wrappers for BT HAL callback which execute them in main
> thread instead of notification_handler() thread. Otherwise test
> execution is prone to race conditions since we do not provide any
> locking mechanism for tester.

In my opinion, this is becoming too messy. I'm getting races even
inside the emulator code: sometimes bthost->ncmd becomes zero before a
HCI command is sent by the emulated host because the Command Status /
Command Complete comes after the command is written to the socket, but
before bthost->ncmd is decremented.

Also try running android-tester under valgrind. At least for me, I get
a few failures that I don't have when running without valgrind (at
least one in HIDHost apparently due to if_bluetooth->enable() not
being called on test setup and thus the tests rely on finishing before
the controller is powered off by the kernel after initialization).

IMHO, the best approach would be to keep all HAL API usage in a
separate process, and keep android-tester single-threaded. Of course,
this could extra complexity for the required IPC between
android-tester and this new process...

Again, I'm not familiar with how HAL API works, all this is just based
on my failed attempt to make android-tester run reliably under
valgrind.

Best Regards,
-- 
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil

^ permalink raw reply


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