Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 6/8] android/handsfree: Add support for HSP AG
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393804249-12392-1-git-send-email-szymon.janc@tieto.com>

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

diff --git a/android/handsfree.c b/android/handsfree.c
index 7a1d697..0b97a5d 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -46,7 +46,9 @@
 #include "src/log.h"
 #include "utils.h"
 
+#define HSP_AG_CHANNEL 12
 #define HFP_AG_CHANNEL 13
+
 #define HFP_AG_FEATURES 0
 
 static struct {
@@ -61,6 +63,9 @@ static struct ipc *hal_ipc = NULL;
 static uint32_t hfp_record_id = 0;
 static GIOChannel *hfp_server = NULL;
 
+static uint32_t hsp_record_id = 0;
+static GIOChannel *hsp_server = NULL;
+
 static void device_set_state(uint8_t state)
 {
 	struct hal_ev_handsfree_conn_state ev;
@@ -460,6 +465,129 @@ static const struct ipc_handler cmd_handlers[] = {
 			sizeof(struct hal_cmd_handsfree_phone_state_change)},
 };
 
+static sdp_record_t *headset_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;
+	uint8_t netid = 0x01;
+	sdp_data_t *network;
+	uint8_t ch = HSP_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, HEADSET_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, HEADSET_PROFILE_ID);
+	profile.version = 0x0102;
+	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]);
+
+	aproto = sdp_list_append(0, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	sdp_set_info_attr(record, "Voice Gateway", 0, 0);
+
+	sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
+
+	sdp_data_free(channel);
+	sdp_list_free(proto[0], NULL);
+	sdp_list_free(proto[1], NULL);
+	sdp_list_free(apseq, NULL);
+	sdp_list_free(pfseq, NULL);
+	sdp_list_free(aproto, NULL);
+	sdp_list_free(root, NULL);
+	sdp_list_free(svclass_id, NULL);
+
+	return record;
+}
+
+static bool enable_hsp_ag(void)
+{
+	sdp_record_t *rec;
+	GError *err = NULL;
+
+	DBG("");
+
+	hsp_server =  bt_io_listen(NULL, confirm_cb, NULL, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+					BT_IO_OPT_CHANNEL, HSP_AG_CHANNEL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_INVALID);
+	if (!hsp_server) {
+		error("Failed to listen on Headset rfcomm: %s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
+	rec = headset_ag_record();
+	if (!rec) {
+		error("Failed to allocate Headset record");
+		goto failed;
+	}
+
+	if (bt_adapter_add_record(rec, 0) < 0) {
+		error("Failed to register Headset record");
+		sdp_record_free(rec);
+		goto failed;
+	}
+
+	hsp_record_id = rec->handle;
+
+	return true;
+
+failed:
+	g_io_channel_shutdown(hsp_server, TRUE, NULL);
+	g_io_channel_unref(hsp_server);
+	hsp_server = NULL;
+
+	return false;
+}
+
+static void cleanup_hsp_ag(void)
+{
+	if (hsp_server) {
+		g_io_channel_shutdown(hsp_server, TRUE, NULL);
+		g_io_channel_unref(hsp_server);
+		hsp_server = NULL;
+	}
+
+	if (hsp_record_id > 0) {
+		bt_adapter_remove_record(hsp_record_id);
+		hsp_record_id = 0;
+	}
+}
+
 static sdp_record_t *hfp_ag_record(void)
 {
 	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
@@ -597,9 +725,14 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 
 	bacpy(&adapter_addr, addr);
 
-	if (!enable_hfp_ag())
+	if (!enable_hsp_ag())
 		return false;
 
+	if (!enable_hfp_ag()) {
+		cleanup_hsp_ag();
+		return false;
+	}
+
 	hal_ipc = ipc;
 	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
@@ -615,4 +748,5 @@ void bt_handsfree_unregister(void)
 	hal_ipc = NULL;
 
 	cleanup_hfp_ag();
+	cleanup_hsp_ag();
 }
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v3 5/8] android/socket: Reserve channel for HSP AG
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393804249-12392-1-git-send-email-szymon.janc@tieto.com>

---
 android/socket.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index 7bc77ed..e9c7675 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -48,7 +48,8 @@
 #define RFCOMM_CHANNEL_MAX 30
 
 #define OPP_DEFAULT_CHANNEL	9
-#define HFAG_DEFAULT_CHANNEL	13
+#define HSP_AG_DEFAULT_CHANNEL	12
+#define HFP_AG_DEFAULT_CHANNEL	13
 #define PBAP_DEFAULT_CHANNEL	15
 #define MAP_MAS_DEFAULT_CHANNEL	16
 
@@ -376,10 +377,19 @@ static const struct profile_info {
 } profiles[] = {
 	{
 		.uuid = {
+			0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x10, 0x00,
+			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+		},
+		.channel = HSP_AG_DEFAULT_CHANNEL,
+		.svc_hint = 0,
+		.sec_level = BT_IO_SEC_MEDIUM,
+		.create_record = NULL
+	}, {
+		.uuid = {
 			0x00, 0x00, 0x11, 0x1F, 0x00, 0x00, 0x10, 0x00,
 			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
 		},
-		.channel = HFAG_DEFAULT_CHANNEL,
+		.channel = HFP_AG_DEFAULT_CHANNEL,
 		.svc_hint = 0,
 		.sec_level = BT_IO_SEC_MEDIUM,
 		.create_record = NULL
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v3 4/8] android/handsfree: Factor out HFP AG enable code
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393804249-12392-1-git-send-email-szymon.janc@tieto.com>

This is in preparation for support to not enable HFP AG when
initializing HAL.
---
 android/handsfree.c | 77 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 49 insertions(+), 28 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index cfdcc1a..7a1d697 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -56,10 +56,10 @@ static struct {
 } device;
 
 static bdaddr_t adapter_addr;
-static uint32_t record_id = 0;
 static struct ipc *hal_ipc = NULL;
 
-static GIOChannel *server = NULL;
+static uint32_t hfp_record_id = 0;
+static GIOChannel *hfp_server = NULL;
 
 static void device_set_state(uint8_t state)
 {
@@ -460,7 +460,7 @@ static const struct ipc_handler cmd_handlers[] = {
 			sizeof(struct hal_cmd_handsfree_phone_state_change)},
 };
 
-static sdp_record_t *handsfree_ag_record(void)
+static sdp_record_t *hfp_ag_record(void)
 {
 	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
 	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
@@ -532,27 +532,28 @@ static sdp_record_t *handsfree_ag_record(void)
 	return record;
 }
 
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
+static bool enable_hfp_ag(void)
 {
 	sdp_record_t *rec;
 	GError *err = NULL;
 
 	DBG("");
 
-	bacpy(&adapter_addr, addr);
+	if (hfp_server)
+		return false;
 
-	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) {
+	hfp_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 (!hfp_server) {
 		error("Failed to listen on Handsfree rfcomm: %s", err->message);
 		g_error_free(err);
-		return false;
+		goto failed;
 	}
 
-	rec = handsfree_ag_record();
+	rec = hfp_ag_record();
 	if (!rec) {
 		error("Failed to allocate Handsfree record");
 		goto failed;
@@ -563,22 +564,49 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 		sdp_record_free(rec);
 		goto failed;
 	}
-	record_id = rec->handle;
 
-	hal_ipc = ipc;
-	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
-						G_N_ELEMENTS(cmd_handlers));
+	hfp_record_id = rec->handle;
 
 	return true;
 
 failed:
-	g_io_channel_shutdown(server, TRUE, NULL);
-	g_io_channel_unref(server);
-	server = NULL;
+	g_io_channel_shutdown(hfp_server, TRUE, NULL);
+	g_io_channel_unref(hfp_server);
+	hfp_server = NULL;
 
 	return false;
 }
 
+static void cleanup_hfp_ag(void)
+{
+	if (hfp_server) {
+		g_io_channel_shutdown(hfp_server, TRUE, NULL);
+		g_io_channel_unref(hfp_server);
+		hfp_server = NULL;
+	}
+
+	if (hfp_record_id > 0) {
+		bt_adapter_remove_record(hfp_record_id);
+		hfp_record_id = 0;
+	}
+}
+
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
+{
+	DBG("");
+
+	bacpy(&adapter_addr, addr);
+
+	if (!enable_hfp_ag())
+		return false;
+
+	hal_ipc = ipc;
+	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
+						G_N_ELEMENTS(cmd_handlers));
+
+	return true;
+}
+
 void bt_handsfree_unregister(void)
 {
 	DBG("");
@@ -586,12 +614,5 @@ void bt_handsfree_unregister(void)
 	ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
 	hal_ipc = NULL;
 
-	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;
+	cleanup_hfp_ag();
 }
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v3 3/8] android: Pass mode parameter to registered services
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393804249-12392-1-git-send-email-szymon.janc@tieto.com>

---
 android/a2dp.c      |  2 +-
 android/a2dp.h      |  2 +-
 android/avrcp.c     |  2 +-
 android/avrcp.h     |  2 +-
 android/bluetooth.c |  2 +-
 android/bluetooth.h |  2 +-
 android/handsfree.c |  2 +-
 android/handsfree.h |  2 +-
 android/hidhost.c   |  2 +-
 android/hidhost.h   |  2 +-
 android/main.c      | 14 +++++++-------
 android/pan.c       |  2 +-
 android/pan.h       |  2 +-
 android/socket.c    |  2 +-
 android/socket.h    |  2 +-
 15 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 180d015..4ea16e2 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1564,7 +1564,7 @@ retry:
 						audio_disconnected);
 }
 
-bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	GError *err = NULL;
 	sdp_record_t *rec;
diff --git a/android/a2dp.h b/android/a2dp.h
index b41a178..8a70407 100644
--- a/android/a2dp.h
+++ b/android/a2dp.h
@@ -21,5 +21,5 @@
  *
  */
 
-bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_a2dp_unregister(void);
diff --git a/android/avrcp.c b/android/avrcp.c
index 678c321..b65f35c 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -364,7 +364,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	DBG("%s connected", address);
 }
 
-bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	GError *err = NULL;
 	sdp_record_t *rec;
diff --git a/android/avrcp.h b/android/avrcp.h
index 3dcffeb..11e79b7 100644
--- a/android/avrcp.h
+++ b/android/avrcp.h
@@ -21,7 +21,7 @@
  *
  */
 
-bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_avrcp_unregister(void);
 
 void bt_avrcp_connect(const bdaddr_t *dst);
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 8ad7d5d..6d94904 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3285,7 +3285,7 @@ static const struct ipc_handler cmd_handlers[] = {
 	{ handle_le_test_mode_cmd, true, sizeof(struct hal_cmd_le_test_mode) },
 };
 
-void bt_bluetooth_register(struct ipc *ipc)
+void bt_bluetooth_register(struct ipc *ipc, uint8_t mode)
 {
 	DBG("");
 
diff --git a/android/bluetooth.h b/android/bluetooth.h
index fbc850d..1c177be 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -31,7 +31,7 @@ void bt_bluetooth_cleanup(void);
 
 void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
 
-void bt_bluetooth_register(struct ipc *ipc);
+void bt_bluetooth_register(struct ipc *ipc, uint8_t mode);
 void bt_bluetooth_unregister(void);
 
 int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint);
diff --git a/android/handsfree.c b/android/handsfree.c
index 81ddcc7..cfdcc1a 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -532,7 +532,7 @@ static sdp_record_t *handsfree_ag_record(void)
 	return record;
 }
 
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	sdp_record_t *rec;
 	GError *err = NULL;
diff --git a/android/handsfree.h b/android/handsfree.h
index 3ede819..e5eff47 100644
--- a/android/handsfree.h
+++ b/android/handsfree.h
@@ -21,5 +21,5 @@
  *
  */
 
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_handsfree_unregister(void);
diff --git a/android/hidhost.c b/android/hidhost.c
index e469210..4226f69 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -1330,7 +1330,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	}
 }
 
-bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	GError *err = NULL;
 
diff --git a/android/hidhost.h b/android/hidhost.h
index 1017195..e6b87ed 100644
--- a/android/hidhost.h
+++ b/android/hidhost.h
@@ -21,5 +21,5 @@
  *
  */
 
-bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_hid_unregister(void);
diff --git a/android/main.c b/android/main.c
index f7fe9c8..c6e08eb 100644
--- a/android/main.c
+++ b/android/main.c
@@ -84,43 +84,43 @@ static void service_register(const void *buf, uint16_t len)
 
 	switch (m->service_id) {
 	case HAL_SERVICE_ID_BLUETOOTH:
-		bt_bluetooth_register(hal_ipc);
+		bt_bluetooth_register(hal_ipc, m->mode);
 
 		break;
 	case HAL_SERVICE_ID_SOCKET:
-		bt_socket_register(hal_ipc, &adapter_bdaddr);
+		bt_socket_register(hal_ipc, &adapter_bdaddr, m->mode);
 
 		break;
 	case HAL_SERVICE_ID_HIDHOST:
-		if (!bt_hid_register(hal_ipc, &adapter_bdaddr)) {
+		if (!bt_hid_register(hal_ipc, &adapter_bdaddr, m->mode)) {
 			status = HAL_STATUS_FAILED;
 			goto failed;
 		}
 
 		break;
 	case HAL_SERVICE_ID_A2DP:
-		if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr)) {
+		if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr, m->mode)) {
 			status = HAL_STATUS_FAILED;
 			goto failed;
 		}
 
 		break;
 	case HAL_SERVICE_ID_PAN:
-		if (!bt_pan_register(hal_ipc, &adapter_bdaddr)) {
+		if (!bt_pan_register(hal_ipc, &adapter_bdaddr, m->mode)) {
 			status = HAL_STATUS_FAILED;
 			goto failed;
 		}
 
 		break;
 	case HAL_SERVICE_ID_AVRCP:
-		if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr)) {
+		if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr, m->mode)) {
 			status = HAL_STATUS_FAILED;
 			goto failed;
 		}
 
 		break;
 	case HAL_SERVICE_ID_HANDSFREE:
-		if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr)) {
+		if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr, m->mode)) {
 			status = HAL_STATUS_FAILED;
 			goto failed;
 		}
diff --git a/android/pan.c b/android/pan.c
index 1e404ab..ce1f677 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -779,7 +779,7 @@ static sdp_record_t *pan_record(void)
 	return record;
 }
 
-bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	sdp_record_t *rec;
 	int err;
diff --git a/android/pan.h b/android/pan.h
index 2045ac5..cfbea96 100644
--- a/android/pan.h
+++ b/android/pan.h
@@ -21,5 +21,5 @@
  *
  */
 
-bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_pan_unregister(void);
diff --git a/android/socket.c b/android/socket.c
index afa2008..7bc77ed 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -1129,7 +1129,7 @@ static const struct ipc_handler cmd_handlers[] = {
 	{ handle_connect, false, sizeof(struct hal_cmd_socket_connect) },
 };
 
-void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr)
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 {
 	size_t i;
 
diff --git a/android/socket.h b/android/socket.h
index a1eca5a..b0e78c6 100644
--- a/android/socket.h
+++ b/android/socket.h
@@ -28,5 +28,5 @@ struct hal_sock_connect_signal {
 	int     status;
 } __attribute__((packed));
 
-void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr);
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
 void bt_socket_unregister(void);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v3 2/8] android/hal: Update services register commands with mode parameter
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393804249-12392-1-git-send-email-szymon.janc@tieto.com>

---
 android/hal-a2dp.c      | 1 +
 android/hal-avrcp.c     | 1 +
 android/hal-bluetooth.c | 1 +
 android/hal-handsfree.c | 1 +
 android/hal-hidhost.c   | 1 +
 android/hal-msg.h       | 3 +++
 android/hal-pan.c       | 1 +
 7 files changed, 9 insertions(+)

diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index c898995..ac495a1 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -109,6 +109,7 @@ static bt_status_t init(btav_callbacks_t *callbacks)
 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
 
 	cmd.service_id = HAL_SERVICE_ID_A2DP;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-avrcp.c b/android/hal-avrcp.c
index 46e25a0..a720a1e 100644
--- a/android/hal-avrcp.c
+++ b/android/hal-avrcp.c
@@ -220,6 +220,7 @@ static bt_status_t init(btrc_callbacks_t *callbacks)
 				sizeof(ev_handlers) / sizeof(ev_handlers[0]));
 
 	cmd.service_id = HAL_SERVICE_ID_AVRCP;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 6871f5d..832183e 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -442,6 +442,7 @@ static int init(bt_callbacks_t *callbacks)
 	}
 
 	cmd.service_id = HAL_SERVICE_ID_SOCKET;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	status = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, NULL, NULL, NULL);
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 1b150c3..7a28e0f 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -212,6 +212,7 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
 
 	cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index c758d2a..16253e3 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -354,6 +354,7 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
 
 	cmd.service_id = HAL_SERVICE_ID_HIDHOST;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 7b6e46d..8eb97c3 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -54,9 +54,12 @@ static const char BLUEZ_HAL_SK_PATH[] = "\0bluez_hal_socket";
 
 #define HAL_OP_STATUS			IPC_OP_STATUS
 
+#define HAL_MODE_DEFAULT		0x00
+
 #define HAL_OP_REGISTER_MODULE		0x01
 struct hal_cmd_register_module {
 	uint8_t service_id;
+	uint8_t mode;
 } __attribute__((packed));
 
 #define HAL_OP_UNREGISTER_MODULE	0x02
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 5ee49ef..f383081 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -157,6 +157,7 @@ static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
 
 	cmd.service_id = HAL_SERVICE_ID_PAN;
+	cmd.mode = HAL_MODE_DEFAULT;
 
 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
 					sizeof(cmd), &cmd, 0, NULL, NULL);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This will allow to run daemon services in non-default mode.
---
 android/hal-ipc-api.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
index 0518c2f..6bf9af3 100644
--- a/android/hal-ipc-api.txt
+++ b/android/hal-ipc-api.txt
@@ -124,12 +124,16 @@ Core Service (ID 0)
 	Opcode 0x01 - Register module command/response
 
 		Command parameters: Service id (1 octet)
+		                    Mode (1 octet)
 		Response parameters: <none>
 
 		In case a command is sent for an undeclared service ID, it will
 		be rejected. Also there will be no notifications for undeclared
 		service ID.
 
+		Valid Mode values: 0x00 = Default Mode
+		                   0xXX = as defined by service
+
 		In case of an error, the error response will be returned.
 
 	Opcode 0x02 - Unregister module command/response
@@ -749,6 +753,8 @@ Bluetooth Handsfree HAL (ID 5)
 
 Android HAL name: "handsfree" (BT_PROFILE_HANDSFREE_ID)
 
+	Service modes:               0x01 = Headset Profile only mode
+
 	Opcode 0x00 - Error response
 
 		Response parameters: Status (1 octet)
-- 
1.8.5.3


^ permalink raw reply related

* PS3 BD Remote Control - always connected problem
From: PhobosK @ 2014-03-02 22:41 UTC (permalink / raw)
  To: linux-bluetooth

Hello,
I have a problem with my PS3 BD Remote Control.
I am running Gentoo with kernel 3.13.3 and bluez 5.15.
I use the PS3 BD Remote Control in XBMC and it works fine, but it stays
connected all the time and the battery is drained very fast... like for
a week. 

There used to be an option in bluez 4.x that helped in fixing the
problem (PS3_REMOTE_TIMEOUT var in the src code) but not anymore.
Now when I try using the IdleTimeout var in input.conf, when the timeout
is reached the device is removed and it cannot be created again nor it
can be used anymore without restarting the bluetooth service (I
use systemd, not openrc if this matters at all).... 


Can anyone help me with this please?

-- 
PhobosK

^ permalink raw reply

* Re: [PATCH 01/13] android/hal-gatt-api: Add Server Register Notification
From: Szymon Janc @ 2014-03-02 22:02 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1393586404-25190-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Friday 28 of February 2014 12:19:52 Grzegorz Kolodziejczyk wrote:
> ---
>  android/hal-ipc-api.txt | 5 +++++
>  android/hal-msg.h       | 7 +++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
> index 04c0b7c..bed8caf 100644
> --- a/android/hal-ipc-api.txt
> +++ b/android/hal-ipc-api.txt
> @@ -1950,6 +1950,11 @@ Android HAL name: "gatt" (BT_PROFILE_GATT_ID)
>  		                         Server Interface (4 octets)
> 
>  	Opcode 0x93 - Register Server notification
> +
> +		Notification parameters: Status (4 octets)
> +		                         Server (4 octets)
> +		                         UUID (16 octets)
> +
>  	Opcode 0x94 - Connection notification
>  	Opcode 0x95 - Service Added notification
>  	Opcode 0x96 - Included Service Added notification
> diff --git a/android/hal-msg.h b/android/hal-msg.h
> index 95ce551..340f7ee 100644
> --- a/android/hal-msg.h
> +++ b/android/hal-msg.h
> @@ -1398,3 +1398,10 @@ struct hal_ev_gatt_client_listen {
>  	int32_t status;
>  	int32_t server_if;
>  } __attribute__((packed));
> +
> +#define HAL_EV_GATT_SERVER_REGISTER		0x93
> +struct hal_ev_gatt_server_register {
> +	int32_t status;
> +	int32_t server_if;
> +	uint8_t uuid[16];
> +} __attribute__((packed));

All patches in this set are now applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH 01/18] android/hal-gatt-api: Add Client Register event
From: Szymon Janc @ 2014-03-02 22:02 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1393583043-23455-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Friday 28 of February 2014 11:23:46 Jakub Tyszkowski wrote:
> ---
>  android/hal-ipc-api.txt | 5 +++++
>  android/hal-msg.h       | 7 +++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
> index 1a19c80..58c05a9 100644
> --- a/android/hal-ipc-api.txt
> +++ b/android/hal-ipc-api.txt
> @@ -1797,6 +1797,11 @@ Android HAL name: "gatt" (BT_PROFILE_GATT_ID)
>  		In case of an error, the error response will be returned.
> 
>  	Opcode 0x81 - Register Client notification
> +
> +		Notification parameters: Status (4 octets)
> +		                         Client Interface (4 octets)
> +		                         UUID (16 octets)
> +
>  	Opcode 0x82 - Scan Result notification
>  	Opcode 0x83 - Connect Device notification
>  	Opcode 0x84 - Disconnect Device notification
> diff --git a/android/hal-msg.h b/android/hal-msg.h
> index bde9717..9f7f9e9 100644
> --- a/android/hal-msg.h
> +++ b/android/hal-msg.h
> @@ -1236,3 +1236,10 @@ struct hal_ev_avrcp_passthrough_cmd {
>  	uint8_t id;
>  	uint8_t state;
>  } __attribute__((packed));
> +
> +#define HAL_EV_GATT_CLIENT_REGISTER_CLIENT	0x81
> +struct hal_ev_gatt_client_register_client {
> +	int32_t status;
> +	int32_t client_if;
> +	uint8_t app_uuid[16];
> +} __attribute__((packed));

All patches in this set are now applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH v2 1/7] android: Add flags parameter to register service command
From: Szymon Janc @ 2014-03-02 20:53 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <EC40658F-2ED8-42B0-8682-375DE769B78A@holtmann.org>

Hi Marcel,

On Sunday 02 of March 2014 09:56:15 Marcel Holtmann wrote:
> Hi Szymon,
> 
> >>> This will allow to configure daemon services.
> >>> ---
> >>> android/hal-a2dp.c      | 1 +
> >>> android/hal-avrcp.c     | 1 +
> >>> android/hal-bluetooth.c | 1 +
> >>> android/hal-handsfree.c | 1 +
> >>> android/hal-hidhost.c   | 1 +
> >>> android/hal-ipc-api.txt | 7 +++++++
> >> 
> >> please do not mix code with API docs updates.
> > 
> > OK.
> > 
> >>> android/hal-msg.h       | 1 +
> >>> android/hal-pan.c       | 1 +
> >>> 8 files changed, 14 insertions(+)
> >>> 
> >>> diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
> >>> index c898995..87d89a2 100644
> >>> --- a/android/hal-a2dp.c
> >>> +++ b/android/hal-a2dp.c
> >>> @@ -109,6 +109,7 @@ static bt_status_t init(btav_callbacks_t *callbacks)
> >>> 
> >>> 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
> >>> 	
> >>> 	cmd.service_id = HAL_SERVICE_ID_A2DP;
> >>> 
> >>> +	cmd.flags = 0;
> >>> 
> >>> 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> >>> 	
> >>> 					sizeof(cmd), &cmd, 0, NULL, NULL);
> >>> 
> >>> diff --git a/android/hal-avrcp.c b/android/hal-avrcp.c
> >>> index 46e25a0..4907f4a 100644
> >>> --- a/android/hal-avrcp.c
> >>> +++ b/android/hal-avrcp.c
> >>> @@ -220,6 +220,7 @@ static bt_status_t init(btrc_callbacks_t *callbacks)
> >>> 
> >>> 				sizeof(ev_handlers) / sizeof(ev_handlers[0]));
> >>> 	
> >>> 	cmd.service_id = HAL_SERVICE_ID_AVRCP;
> >>> 
> >>> +	cmd.flags = 0;
> >>> 
> >>> 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> >>> 	
> >>> 					sizeof(cmd), &cmd, 0, NULL, NULL);
> >>> 
> >>> diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
> >>> index 6871f5d..4b31ff1 100644
> >>> --- a/android/hal-bluetooth.c
> >>> +++ b/android/hal-bluetooth.c
> >>> @@ -442,6 +442,7 @@ static int init(bt_callbacks_t *callbacks)
> >>> 
> >>> 	}
> >>> 	
> >>> 	cmd.service_id = HAL_SERVICE_ID_SOCKET;
> >>> 
> >>> +	cmd.flags = 0;
> >>> 
> >>> 	status = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> >>> 	
> >>> 					sizeof(cmd), &cmd, NULL, NULL, NULL);
> >>> 
> >>> diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
> >>> index 1b150c3..422f52c 100644
> >>> --- a/android/hal-handsfree.c
> >>> +++ b/android/hal-handsfree.c
> >>> @@ -212,6 +212,7 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
> >>> 
> >>> 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
> >>> 	
> >>> 	cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
> >>> 
> >>> +	cmd.flags = 0;
> >>> 
> >>> 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> >>> 	
> >>> 					sizeof(cmd), &cmd, 0, NULL, NULL);
> >>> 
> >>> diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
> >>> index c758d2a..fe1b4df 100644
> >>> --- a/android/hal-hidhost.c
> >>> +++ b/android/hal-hidhost.c
> >>> @@ -354,6 +354,7 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
> >>> 
> >>> 				sizeof(ev_handlers)/sizeof(ev_handlers[0]));
> >>> 	
> >>> 	cmd.service_id = HAL_SERVICE_ID_HIDHOST;
> >>> 
> >>> +	cmd.flags = 0;
> >>> 
> >>> 	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> >>> 	
> >>> 					sizeof(cmd), &cmd, 0, NULL, NULL);
> >>> 
> >>> diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
> >>> index 1a19c80..f68324d 100644
> >>> --- a/android/hal-ipc-api.txt
> >>> +++ b/android/hal-ipc-api.txt
> >>> @@ -124,12 +124,16 @@ Core Service (ID 0)
> >>> 
> >>> 	Opcode 0x01 - Register module command/response
> >>> 	
> >>> 		Command parameters: Service id (1 octet)
> >>> 
> >>> +		                    Flags (1 octet)
> >> 
> >> We might better go with a Flags (4 octets) here. Otherwise you only have
> >> 8
> >> options which might be enough or not. Your choice.
> >> 
> >> Or instead of a bit mask, we do a Configuration (1 octet) were we have
> >> the
> >> default configuration with 0x00 and then alternatives with all other
> >> values. That might be actually a bit better.
> > 
> > I'll see how it goes with configuration options, but flags could be used
> > also to enable eg. debug options which might be clumsy without flags.
> 
> what debug options are you thinking about?
> 
> I also think we should just call it Mode (1 octet). Keep it simple.

Like enabling debug linkkeys or AT dumping in handsfree. But I guess we can 
work this out later, so I'll go with 'Mode' as you suggested.

Will send V3 shortly.
 
> >>> 		Response parameters: <none>
> >>> 		
> >>> 		In case a command is sent for an undeclared service ID, it will
> >>> 		be rejected. Also there will be no notifications for undeclared
> >>> 		service ID.
> >>> 
> >>> +		Flags parameter values should be defined as needed by
> >>> +		respective services.
> >>> +
> >>> 
> >>> 		In case of an error, the error response will be returned.
> >>> 	
> >>> 	Opcode 0x02 - Unregister module command/response
> >>> 
> >>> @@ -749,6 +753,9 @@ Bluetooth Handsfree HAL (ID 5)
> >>> 
> >>> Android HAL name: "handsfree" (BT_PROFILE_HANDSFREE_ID)
> >>> 
> >>> +	Service flags:               0x01 = Disable HSP AG
> >>> +	                             0x02 = Disable HFP AG
> >>> +
> >> 
> >> If you do not want HSP and HFP, then there is no point in registering
> >> handsfree ID at all. I am tending currently towards the configuration
> >> option.
> >> 
> >> 	0x00 = Provide Handsfree profile
> >> 	0x01 = Provide Headset profile
> >> 
> >> There is really no point in providing both? Or is there a case where you
> >> would provide both?
> > 
> > Android on phones provides both. On tablets HSP only. So we could go with
> > 0x00 = Provide HFP and HSP
> > 0x01 = Provide HSP only
> > 
> > or just with single flag to disable HFP.
> 
> Do we really want to expose HSP gateway when HFP is available. I am not even
> sure this makes sense. With Bluedroid, are they using the same RFCOMM
> channel or how does that actually work. You can not connect them at the
> same time anyway.
> 
> I would really go for the simple case of either Handsfree or Headset
> profile, but not both.

Those are running on separate channels and with this serie we have the same.
If either is connected, another connection will be refused.

I'm not sure why having both HSP and HFP would be of any problem..


-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH 0/6] Initial HAL test AVRCP api support
From: Luiz Augusto von Dentz @ 2014-03-02 18:57 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1393613928-22264-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Fri, Feb 28, 2014 at 8:58 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> Patchset contains initial AVRCP api support for HAL test.
>
> Ravi kumar Veeramally (6):
>   android/client: Add AVRCP get_play_status_rsp support
>   android/client: Add AVRCP get_element_attr_rsp support
>   android/client: Add AVRCP set_volume support
>   android/client: Add AVRCP get_play_status_cb support
>   android/client: Add AVRCP get_element_attr_cb support
>   android/client: Add AVRCP volume_change_cb support
>
>  android/client/if-rc.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 151 insertions(+)
>
> --
> 1.8.3.2

This doesn't help much with AVRCP since the requests need to be
responded rather quickly we might need to have them auto responded if
we really want hal-tester to be usable.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [bluez-5.14] connect fails with 'org.bluez.Error.NotAvailable'
From: Tobias Jakobi @ 2014-03-02 18:54 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_PVX=97RPVUJ5qx9k-OFNt=xidLrwgL6qK9QTTRBJHd+Q@mail.gmail.com>

Anderson Lizardo wrote:
> I misunderstood the first output, it was actually the "info" command
> for the server from the client side. I thought it was the "show"
> command on the server side. That explains the missing "Powered"
> property :)
> 
I see. Any idea how to isolate where the NotAvailable error origins from?

With best wishes,
Tobias


^ permalink raw reply

* [PATCH BlueZ 14/16] android/avrcp: Bump version to 1.3
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/avrcp.c b/android/avrcp.c
index 875c6e2..268c1b1 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -355,7 +355,7 @@ static sdp_record_t *avrcp_record(void)
 	sdp_record_t *record;
 	sdp_data_t *psm, *version, *features;
 	uint16_t lp = L2CAP_PSM_AVCTP;
-	uint16_t avrcp_ver = 0x0100, avctp_ver = 0x0103;
+	uint16_t avrcp_ver = 0x0103, avctp_ver = 0x0103;
 	uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
 					AVRCP_FEATURE_CATEGORY_2 |
 					AVRCP_FEATURE_CATEGORY_3 |
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 13/16] android/avrcp: Add handler for RegisterNotification command
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/android/avrcp.c b/android/avrcp.c
index 6ef8d0a..875c6e2 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -252,10 +252,58 @@ static void handle_set_player_attrs_value(const void *buf, uint16_t len)
 
 static void handle_register_notification(const void *buf, uint16_t len)
 {
+	struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
+	uint8_t status;
+	struct avrcp_request *req;
+	uint8_t pdu[IPC_MTU];
+	size_t pdu_len = 1;
+	int ret;
+
 	DBG("");
 
+	req = pop_request(AVRCP_REGISTER_NOTIFICATION);
+	if (!req) {
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	pdu[0] = cmd->event;
+
+	switch (cmd->event) {
+	case AVRCP_EVENT_STATUS_CHANGED:
+	case AVRCP_EVENT_TRACK_CHANGED:
+	case AVRCP_EVENT_TRACK_REACHED_END:
+	case AVRCP_EVENT_TRACK_REACHED_START:
+	case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
+		if (cmd->len > 0) {
+			memcpy(&pdu[1], cmd->data, cmd->len);
+			pdu_len += cmd->len;
+		}
+		break;
+	case AVRCP_EVENT_SETTINGS_CHANGED:
+		pdu[1] = cmd->len / sizeof(struct hal_avrcp_player_attr_value);
+		memcpy(&pdu[2], cmd->data, cmd->len);
+		break;
+	default:
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	ret = avrcp_send(req->dev->session, req->transaction, cmd->type,
+					AVC_SUBUNIT_PANEL, req->pdu_id,
+					pdu, pdu_len);
+	if (ret < 0) {
+		status = HAL_STATUS_FAILED;
+		g_free(req);
+		goto done;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+	g_free(req);
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
-			HAL_OP_AVRCP_REGISTER_NOTIFICATION, HAL_STATUS_FAILED);
+			HAL_OP_AVRCP_REGISTER_NOTIFICATION, status);
 }
 
 static void handle_set_volume(const void *buf, uint16_t len)
@@ -568,6 +616,37 @@ static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
 
 }
 
+static ssize_t handle_register_notification_cmd(struct avrcp *session,
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
+{
+	struct avrcp_device *dev = user_data;
+	struct avrcp_request *req;
+	struct hal_ev_avrcp_register_notification ev;
+
+	if (params_len != 5)
+		return -EINVAL;
+
+	req = g_new0(struct avrcp_request, 1);
+	req->dev = dev;
+	req->pdu_id = AVRCP_REGISTER_NOTIFICATION;
+	req->transaction = transaction;
+
+	g_queue_push_tail(dev->queue, req);
+
+	ev.event = params[0];
+	ev.param = bt_get_be32(&params[1]);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
+					HAL_EV_AVRCP_REGISTER_NOTIFICATION,
+					sizeof(ev), &ev);
+
+	return -EAGAIN;
+
+}
+
 static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_CAPABILITIES,
 					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
@@ -578,6 +657,9 @@ static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_ELEMENT_ATTRIBUTES,
 					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					handle_get_element_attrs_cmd },
+		{ AVRCP_REGISTER_NOTIFICATION,
+					AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
+					handle_register_notification_cmd },
 		{ },
 };
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 12/16] android/avrcp: Add handler for GetElementAttributes command
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/android/avrcp.c b/android/avrcp.c
index 3ac8223..6ef8d0a 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -167,12 +167,79 @@ static void handle_get_player_values_text(const void *buf, uint16_t len)
 			HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED);
 }
 
+static void write_element_text(uint8_t id, uint8_t text_len, uint8_t *text,
+						uint8_t *pdu, size_t *len)
+{
+	uint16_t charset = 106;
+
+	bt_put_be32(id, pdu);
+	pdu += 4;
+	*len += 4;
+
+	bt_put_be16(charset, pdu);
+	pdu += 2;
+	*len += 2;
+
+	bt_put_be16(text_len, pdu);
+	pdu += 2;
+	*len += 2;
+
+	memcpy(pdu, text, text_len);
+	*len += text_len;
+}
+
+static void write_element_attrs(uint8_t *ptr, uint8_t number, uint8_t *pdu,
+								size_t *len)
+{
+	int i;
+
+	for (i = 0; i < number; i++) {
+		struct hal_avrcp_player_setting_text *text = (void *) ptr;
+
+		write_element_text(text->id, text->len, text->text, pdu, len);
+
+		ptr += sizeof(*text) + text->len;
+		pdu += *len;
+	}
+}
+
 static void handle_get_element_attrs_text(const void *buf, uint16_t len)
 {
+	struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf;
+	uint8_t status;
+	struct avrcp_request *req;
+	uint8_t pdu[IPC_MTU];
+	uint8_t *ptr;
+	size_t pdu_len;
+	int ret;
+
 	DBG("");
 
+	req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES);
+	if (!req) {
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	ptr = (uint8_t *) &cmd->values[0];
+	pdu_len = 0;
+	write_element_attrs(ptr, cmd->number, pdu, &pdu_len);
+
+	ret = avrcp_send(req->dev->session, req->transaction, AVC_CTYPE_STABLE,
+					AVC_SUBUNIT_PANEL, req->pdu_id,
+					pdu, pdu_len);
+	if (ret < 0) {
+		status = HAL_STATUS_FAILED;
+		g_free(req);
+		goto done;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+	g_free(req);
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
-			HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, HAL_STATUS_FAILED);
+			HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, status);
 }
 
 static void handle_set_player_attrs_value(const void *buf, uint16_t len)
@@ -460,6 +527,47 @@ static ssize_t handle_get_play_status_cmd(struct avrcp *session,
 	return -EAGAIN;
 }
 
+static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
+{
+	struct avrcp_device *dev = user_data;
+	struct avrcp_request *req;
+	uint8_t buf[IPC_MTU];
+	struct hal_ev_avrcp_get_element_attrs *ev = (void *) buf;
+	int i;
+
+	if (params_len < 9)
+		return -EINVAL;
+
+	ev->number = params[8];
+
+	if (params_len < ev->number * sizeof(uint32_t) + 1)
+		return -EINVAL;
+
+	params += 9;
+	for (i = 0; i < ev->number; i++) {
+		ev->attrs[i] = bt_get_be32(params);
+		params += 4;
+	}
+
+	req = g_new0(struct avrcp_request, 1);
+	req->dev = dev;
+	req->pdu_id = AVRCP_GET_ELEMENT_ATTRIBUTES;
+	req->transaction = transaction;
+
+	g_queue_push_tail(dev->queue, req);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
+					HAL_EV_AVRCP_GET_ELEMENT_ATTRS,
+					sizeof(*ev) + ev->number, ev);
+
+	return -EAGAIN;
+
+}
+
 static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_CAPABILITIES,
 					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
@@ -467,6 +575,9 @@ static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_PLAY_STATUS,
 					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					handle_get_play_status_cmd },
+		{ AVRCP_GET_ELEMENT_ATTRIBUTES,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
+					handle_get_element_attrs_cmd },
 		{ },
 };
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 11/16] android/avrcp: Add handler for GetPlayStatus command
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/android/avrcp.c b/android/avrcp.c
index bcaa66c..3ac8223 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -37,6 +37,7 @@
 #include "avctp.h"
 #include "avrcp-lib.h"
 #include "hal-msg.h"
+#include "ipc-common.h"
 #include "ipc.h"
 #include "bluetooth.h"
 #include "avrcp.h"
@@ -54,18 +55,76 @@ static GSList *devices = NULL;
 static GIOChannel *server = NULL;
 static struct ipc *hal_ipc = NULL;
 
+struct avrcp_request {
+	struct avrcp_device *dev;
+	uint8_t pdu_id;
+	uint8_t transaction;
+};
+
 struct avrcp_device {
 	bdaddr_t	dst;
 	struct avrcp	*session;
 	GIOChannel	*io;
+	GQueue		*queue;
 };
 
+static struct avrcp_request *pop_request(uint8_t pdu_id)
+{
+	GSList *l;
+
+	for (l = devices; l; l = g_slist_next(l)) {
+		struct avrcp_device *dev = l->data;
+		GList *reqs = g_queue_peek_head_link(dev->queue);
+		int i;
+
+		for (i = 0; reqs; reqs = g_list_next(reqs), i++) {
+			struct avrcp_request *req = reqs->data;
+
+			if (req->pdu_id == pdu_id) {
+				g_queue_pop_nth(dev->queue, i);
+				return req;
+			}
+		}
+	}
+
+	return NULL;
+}
+
 static void handle_get_play_status(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_avrcp_get_play_status *cmd = buf;
+	uint8_t status;
+	struct avrcp_request *req;
+	uint8_t pdu[9];
+	int ret;
+
 	DBG("");
 
+	req = pop_request(AVRCP_GET_PLAY_STATUS);
+	if (!req) {
+		status = HAL_STATUS_FAILED;
+		goto done;
+	}
+
+	bt_put_be32(cmd->position, &pdu[0]);
+	bt_put_be32(cmd->duration, &pdu[4]);
+	pdu[8] = cmd->status;
+
+	ret = avrcp_send(req->dev->session, req->transaction, AVC_CTYPE_STABLE,
+					AVC_SUBUNIT_PANEL, req->pdu_id,
+					pdu, sizeof(pdu));
+	if (ret < 0) {
+		status = HAL_STATUS_FAILED;
+		g_free(req);
+		goto done;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+	g_free(req);
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
-			HAL_OP_AVRCP_GET_PLAY_STATUS, HAL_STATUS_FAILED);
+				HAL_OP_AVRCP_GET_PLAY_STATUS, status);
 }
 
 static void handle_list_player_attrs(const void *buf, uint16_t len)
@@ -244,6 +303,9 @@ static void avrcp_device_free(void *data)
 {
 	struct avrcp_device *dev = data;
 
+	g_queue_foreach(dev->queue, (GFunc) g_free, NULL);
+	g_queue_free(dev->queue);
+
 	if (dev->session)
 		avrcp_shutdown(dev->session);
 
@@ -373,10 +435,38 @@ static ssize_t handle_get_capabilities(struct avrcp *session,
 	return -EINVAL;
 }
 
+static ssize_t handle_get_play_status_cmd(struct avrcp *session,
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
+{
+	struct avrcp_device *dev = user_data;
+	struct avrcp_request *req;
+
+	if (params_len != 0)
+		return -EINVAL;
+
+	req = g_new0(struct avrcp_request, 1);
+	req->dev = dev;
+	req->pdu_id = AVRCP_GET_CAPABILITIES;
+	req->transaction = transaction;
+
+	g_queue_push_tail(dev->queue, req);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
+					HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL);
+
+	return -EAGAIN;
+}
+
 static const struct avrcp_control_handler control_handlers[] = {
 		{ AVRCP_GET_CAPABILITIES,
 					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					handle_get_capabilities },
+		{ AVRCP_GET_PLAY_STATUS,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
+					handle_get_play_status_cmd },
 		{ },
 };
 
@@ -433,6 +523,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 									dev);
 	avrcp_set_control_handlers(dev->session, control_handlers, dev);
 
+	dev->queue = g_queue_new();
+
 	/* FIXME: get the real name of the device */
 	avrcp_init_uinput(dev->session, "bluetooth", address);
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 10/16] android/avrcp: Add handler for GetCapabilities command
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp-lib.h |  1 +
 android/avrcp.c     | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 8625425..dda1d28 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -51,6 +51,7 @@
 #define AVRCP_EVENT_TRACK_CHANGED		0x02
 #define AVRCP_EVENT_TRACK_REACHED_END		0x03
 #define AVRCP_EVENT_TRACK_REACHED_START		0x04
+#define AVRCP_EVENT_PLAYBACK_POS_CHANGED	0x05
 #define AVRCP_EVENT_SETTINGS_CHANGED		0x08
 #define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED	0x0a
 #define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED	0x0b
diff --git a/android/avrcp.c b/android/avrcp.c
index 9d86803..bcaa66c 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -26,6 +26,7 @@
 #endif
 
 #include <stdbool.h>
+#include <errno.h>
 #include <glib.h>
 
 #include "btio/btio.h"
@@ -339,6 +340,46 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
 		{ },
 };
 
+static ssize_t handle_get_capabilities(struct avrcp *session,
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
+{
+	uint32_t id = 0x001958;
+
+	if (params_len != 1)
+		return -EINVAL;
+
+	switch (params[0]) {
+	case CAP_COMPANY_ID:
+		params[params_len++] = 1;
+		hton24(&params[params_len], id);
+		return params_len + 3;
+	case CAP_EVENTS_SUPPORTED:
+		/* Android do not provide this info via HAL so the list most
+		 * be hardcoded according to what RegisterNotification can
+		 * actually handle */
+		params[params_len++] = 6;
+		params[params_len++] = AVRCP_EVENT_STATUS_CHANGED;
+		params[params_len++] = AVRCP_EVENT_TRACK_CHANGED;
+		params[params_len++] = AVRCP_EVENT_TRACK_REACHED_END;
+		params[params_len++] = AVRCP_EVENT_TRACK_REACHED_START;
+		params[params_len++] = AVRCP_EVENT_PLAYBACK_POS_CHANGED;
+		params[params_len++] = AVRCP_EVENT_SETTINGS_CHANGED;
+		return params_len;
+	}
+
+	return -EINVAL;
+}
+
+static const struct avrcp_control_handler control_handlers[] = {
+		{ AVRCP_GET_CAPABILITIES,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
+					handle_get_capabilities },
+		{ },
+};
+
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
 	struct avrcp_device *dev;
@@ -390,6 +431,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	avrcp_set_destroy_cb(dev->session, disconnect_cb, dev);
 	avrcp_set_passthrough_handlers(dev->session, passthrough_handlers,
 									dev);
+	avrcp_set_control_handlers(dev->session, control_handlers, dev);
 
 	/* FIXME: get the real name of the device */
 	avrcp_init_uinput(dev->session, "bluetooth", address);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 09/16] android/avrcp-lib: Make hton24 and ntoh24 public
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This avoids duplicating those function everytime.
---
 android/avrcp-lib.c | 12 ------------
 android/avrcp-lib.h | 12 ++++++++++++
 unit/test-avrcp.c   |  7 -------
 3 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 40ff7b3..60c8ba3 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -73,18 +73,6 @@ struct avrcp_header {
 #error "Unknown byte order"
 #endif
 
-static inline uint32_t ntoh24(const uint8_t src[3])
-{
-	return src[0] << 16 | src[1] << 8 | src[2];
-}
-
-static inline void hton24(uint8_t dst[3], uint32_t src)
-{
-	dst[0] = (src & 0xff0000) >> 16;
-	dst[1] = (src & 0x00ff00) >> 8;
-	dst[2] = (src & 0x0000ff);
-}
-
 struct avrcp {
 	struct avctp *conn;
 
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 3df5897..8625425 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -91,6 +91,18 @@ struct avrcp_passthrough_handler {
 
 typedef void (*avrcp_destroy_cb_t) (void *user_data);
 
+static inline uint32_t ntoh24(const uint8_t src[3])
+{
+	return src[0] << 16 | src[1] << 8 | src[2];
+}
+
+static inline void hton24(uint8_t dst[3], uint32_t src)
+{
+	dst[0] = (src & 0xff0000) >> 16;
+	dst[1] = (src & 0x00ff00) >> 8;
+	dst[2] = (src & 0x0000ff);
+}
+
 struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
 void avrcp_shutdown(struct avrcp *session);
 void avrcp_set_destroy_cb(struct avrcp *session, avrcp_destroy_cb_t cb,
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 0294973..695f62c 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -94,13 +94,6 @@ struct context {
 		g_test_add_data_func(name, &data, function);		\
 	} while (0)
 
-static inline void hton24(uint8_t dst[3], uint32_t src)
-{
-	dst[0] = (src & 0xff0000) >> 16;
-	dst[1] = (src & 0x00ff00) >> 8;
-	dst[2] = (src & 0x0000ff);
-}
-
 static void test_debug(const char *str, void *user_data)
 {
 	const char *prefix = user_data;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 08/16] android/avrcp: Add passthrough handler for rewind
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Rewind should be send via HAL not handled directly by uinput otherwise
Android media player might not interpret it correctly.
---
 android/avrcp.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/android/avrcp.c b/android/avrcp.c
index 3d56ccf..9d86803 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -317,8 +317,25 @@ static bool handle_fast_forward(struct avrcp *session, bool pressed,
 	return true;
 }
 
+static bool handle_rewind(struct avrcp *session, bool pressed,
+							void *user_data)
+{
+	struct hal_ev_avrcp_passthrough_cmd ev;
+
+	DBG("pressed %s", pressed ? "true" : "false");
+
+	ev.id = AVC_REWIND;
+	ev.state = pressed;
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
+			HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
+
+	return true;
+}
+
 static const struct avrcp_passthrough_handler passthrough_handlers[] = {
 		{ AVC_FAST_FORWARD, handle_fast_forward },
+		{ AVC_REWIND, handle_rewind },
 		{ },
 };
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 07/16] android/avrcp: Add passthrough handler for fast forward
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Fast forward should be send via HAL not handled directly by uinput
otherwise Android media player might not interpret it correctly.
---
 android/avrcp.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/avrcp.c b/android/avrcp.c
index 678c321..3d56ccf 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -301,6 +301,27 @@ static void disconnect_cb(void *data)
 	avrcp_device_remove(dev);
 }
 
+static bool handle_fast_forward(struct avrcp *session, bool pressed,
+							void *user_data)
+{
+	struct hal_ev_avrcp_passthrough_cmd ev;
+
+	DBG("pressed %s", pressed ? "true" : "false");
+
+	ev.id = AVC_FAST_FORWARD;
+	ev.state = pressed;
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
+			HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev);
+
+	return true;
+}
+
+static const struct avrcp_passthrough_handler passthrough_handlers[] = {
+		{ AVC_FAST_FORWARD, handle_fast_forward },
+		{ },
+};
+
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 {
 	struct avrcp_device *dev;
@@ -350,6 +371,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	}
 
 	avrcp_set_destroy_cb(dev->session, disconnect_cb, dev);
+	avrcp_set_passthrough_handlers(dev->session, passthrough_handlers,
+									dev);
 
 	/* FIXME: get the real name of the device */
 	avrcp_init_uinput(dev->session, "bluetooth", address);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 06/16] android/avrcp-lib: Add pressed status to passthrough handler callback
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds pressed status to passthrough handler callback which is
required by Android HAL for certain keys such as fast forward and rewind.
---
 android/avrcp-lib.c |  6 +-----
 android/avrcp-lib.h |  2 +-
 unit/test-avrcp.c   | 10 ++++++----
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 8854263..40ff7b3 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -205,11 +205,7 @@ static bool handle_passthrough_pdu(struct avctp *conn, uint8_t op,
 	if (handler->func == NULL)
 		return false;
 
-	/* Do not trigger handler on release */
-	if (!pressed)
-		return true;
-
-	return handler->func(session, session->passthrough_data);
+	return handler->func(session, pressed, session->passthrough_data);
 }
 
 struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index 430f545..3df5897 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -86,7 +86,7 @@ struct avrcp_control_handler {
 
 struct avrcp_passthrough_handler {
 	uint8_t op;
-	bool (*func) (struct avrcp *session, void *user_data);
+	bool (*func) (struct avrcp *session, bool pressed, void *user_data);
 };
 
 typedef void (*avrcp_destroy_cb_t) (void *user_data);
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index ac267bb..0294973 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -257,28 +257,30 @@ static void execute_context(struct context *context)
 	destroy_context(context);
 }
 
-static bool handle_play(struct avrcp *session, void *user_data)
+static bool handle_play(struct avrcp *session, bool pressed, void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_volume_up(struct avrcp *session, void *user_data)
+static bool handle_volume_up(struct avrcp *session, bool pressed,
+							void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_channel_up(struct avrcp *session, void *user_data)
+static bool handle_channel_up(struct avrcp *session, bool pressed,
+							void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_select(struct avrcp *session, void *user_data)
+static bool handle_select(struct avrcp *session, bool pressed, void *user_data)
 {
 	DBG("");
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 05/16] android/avrcp-lib: Fix not passing user data of passthrough callback
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/avrcp-lib.c | 2 +-
 android/avrcp-lib.h | 2 +-
 unit/test-avrcp.c   | 8 ++++----
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 7b89ee2..8854263 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -209,7 +209,7 @@ static bool handle_passthrough_pdu(struct avctp *conn, uint8_t op,
 	if (!pressed)
 		return true;
 
-	return handler->func(session);
+	return handler->func(session, session->passthrough_data);
 }
 
 struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index df9f1c6..430f545 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -86,7 +86,7 @@ struct avrcp_control_handler {
 
 struct avrcp_passthrough_handler {
 	uint8_t op;
-	bool (*func) (struct avrcp *session);
+	bool (*func) (struct avrcp *session, void *user_data);
 };
 
 typedef void (*avrcp_destroy_cb_t) (void *user_data);
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index d8484cd..ac267bb 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -257,28 +257,28 @@ static void execute_context(struct context *context)
 	destroy_context(context);
 }
 
-static bool handle_play(struct avrcp *session)
+static bool handle_play(struct avrcp *session, void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_volume_up(struct avrcp *session)
+static bool handle_volume_up(struct avrcp *session, void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_channel_up(struct avrcp *session)
+static bool handle_channel_up(struct avrcp *session, void *user_data)
 {
 	DBG("");
 
 	return true;
 }
 
-static bool handle_select(struct avrcp *session)
+static bool handle_select(struct avrcp *session, void *user_data)
 {
 	DBG("");
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 04/16] android/avrcp-lib: Embed response code into handler table
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This makes the handlers code simpler as they don't need to care about
the response or reject opcode.
---
 android/avrcp-lib.c | 16 ++++++++++++----
 android/avrcp-lib.h |  4 ++--
 unit/test-avrcp.c   | 41 +++++++++++++++++++++--------------------
 3 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 339be16..7b89ee2 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -160,14 +160,22 @@ static ssize_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
 		goto reject;
 	}
 
-	ret = handler->func(session, transaction, code, params_len,
-					pdu->params, session->control_data);
+	ret = handler->func(session, transaction, params_len, pdu->params,
+							session->control_data);
 	if (ret < 0) {
-		if (ret == -EAGAIN)
+		switch (ret) {
+		case -EAGAIN:
 			return ret;
-		goto reject;
+		case -EINVAL:
+			pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
+			goto reject;
+		default:
+			pdu->params[0] = AVRCP_STATUS_INTERNAL_ERROR;
+			goto reject;
+		}
 	}
 
+	*code = handler->rsp;
 	pdu->params_len = htons(ret);
 
 	return AVRCP_HEADER_LENGTH + ret;
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index d7a805b..df9f1c6 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -79,9 +79,9 @@ struct avrcp;
 struct avrcp_control_handler {
 	uint8_t id;
 	uint8_t code;
+	uint8_t rsp;
 	ssize_t (*func) (struct avrcp *session, uint8_t transaction,
-			uint8_t *code, uint16_t params_len, uint8_t *params,
-			void *user_data);
+			uint16_t params_len, uint8_t *params, void *user_data);
 };
 
 struct avrcp_passthrough_handler {
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 2d5711b..d8484cd 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -31,6 +31,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <fcntl.h>
+#include <errno.h>
 #include <sys/socket.h>
 
 #include <glib.h>
@@ -293,61 +294,61 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
 };
 
 static ssize_t avrcp_handle_get_capabilities(struct avrcp *session,
-					uint8_t transaction, uint8_t *code,
-					uint16_t params_len, uint8_t *params,
-					void *user_data)
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
 {
 	uint32_t id = 0x001958;
 
 	if (params_len != 1)
-		goto fail;
+		return -EINVAL;
 
 	switch (params[0]) {
 	case CAP_COMPANY_ID:
 		params[1] = 1;
 		hton24(&params[2], id);
-		*code = AVC_CTYPE_STABLE;
 		return 5;
 	}
 
-fail:
-	params[0] = AVRCP_STATUS_INVALID_PARAM;
-	*code = AVC_CTYPE_REJECTED;
-	return 1;
+	return -EINVAL;
 }
 
 static ssize_t avrcp_handle_list_attributes(struct avrcp *session,
-					uint8_t transaction, uint8_t *code,
-					uint16_t params_len, uint8_t *params,
-					void *user_data)
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
 {
 	DBG("");
 
 	params[0] = 0;
-	*code = AVC_CTYPE_STABLE;
 
 	return 1;
 }
 
 static ssize_t avrcp_handle_get_player_attr_text(struct avrcp *session,
-					uint8_t transaction, uint8_t *code,
-					uint16_t params_len, uint8_t *params,
-					void *user_data)
+						uint8_t transaction,
+						uint16_t params_len,
+						uint8_t *params,
+						void *user_data)
 {
 	DBG("");
 
 	params[0] = 0;
-	*code = AVC_CTYPE_STABLE;
 
 	return 1;
 }
 
 static const struct avrcp_control_handler control_handlers[] = {
-		{ AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
+		{ AVRCP_GET_CAPABILITIES,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					avrcp_handle_get_capabilities },
-		{ AVRCP_LIST_PLAYER_ATTRIBUTES, AVC_CTYPE_STATUS,
+		{ AVRCP_LIST_PLAYER_ATTRIBUTES,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					avrcp_handle_list_attributes },
-		{ AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, AVC_CTYPE_STATUS,
+		{ AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
+					AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
 					avrcp_handle_get_player_attr_text },
 		{ },
 };
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 03/16] android/avrcp-lib: Rework handler callback parameters
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This rework handler callback parameters to make it able to return
proper error such as -EAGAIN to implement asynchronous responses.
---
 android/avrcp-lib.c | 12 +++++++++---
 android/avrcp-lib.h |  5 +++--
 unit/test-avrcp.c   | 42 +++++++++++++++++++++---------------------
 3 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index cdad6ac..339be16 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -125,6 +125,7 @@ static ssize_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
 	struct avrcp_header *pdu = (void *) operands;
 	uint32_t company_id = ntoh24(pdu->company_id);
 	uint16_t params_len = ntohs(pdu->params_len);
+	ssize_t ret;
 
 	if (company_id != IEEEID_BTSIG) {
 		*code = AVC_CTYPE_NOT_IMPLEMENTED;
@@ -159,12 +160,17 @@ static ssize_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
 		goto reject;
 	}
 
-	*code = handler->func(session, transaction, &params_len,
+	ret = handler->func(session, transaction, code, params_len,
 					pdu->params, session->control_data);
+	if (ret < 0) {
+		if (ret == -EAGAIN)
+			return ret;
+		goto reject;
+	}
 
-	pdu->params_len = htons(params_len);
+	pdu->params_len = htons(ret);
 
-	return AVRCP_HEADER_LENGTH + params_len;
+	return AVRCP_HEADER_LENGTH + ret;
 
 reject:
 	pdu->params_len = htons(1);
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
index a33bdfe..d7a805b 100644
--- a/android/avrcp-lib.h
+++ b/android/avrcp-lib.h
@@ -79,8 +79,9 @@ struct avrcp;
 struct avrcp_control_handler {
 	uint8_t id;
 	uint8_t code;
-	uint8_t (*func) (struct avrcp *session, uint8_t transaction,
-			uint16_t *params_len, uint8_t *params, void *user_data);
+	ssize_t (*func) (struct avrcp *session, uint8_t transaction,
+			uint8_t *code, uint16_t params_len, uint8_t *params,
+			void *user_data);
 };
 
 struct avrcp_passthrough_handler {
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 302c331..2d5711b 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -292,54 +292,54 @@ static const struct avrcp_passthrough_handler passthrough_handlers[] = {
 		{ },
 };
 
-static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
-				uint8_t transaction, uint16_t *params_len,
-				uint8_t *params, void *user_data)
+static ssize_t avrcp_handle_get_capabilities(struct avrcp *session,
+					uint8_t transaction, uint8_t *code,
+					uint16_t params_len, uint8_t *params,
+					void *user_data)
 {
 	uint32_t id = 0x001958;
 
-	DBG("params[0] %d params_len %d", params[0], *params_len);
-
-	if (*params_len != 1)
+	if (params_len != 1)
 		goto fail;
 
 	switch (params[0]) {
 	case CAP_COMPANY_ID:
-		*params_len = 5;
 		params[1] = 1;
 		hton24(&params[2], id);
-		return AVC_CTYPE_STABLE;
+		*code = AVC_CTYPE_STABLE;
+		return 5;
 	}
 
 fail:
-	*params_len = 1;
 	params[0] = AVRCP_STATUS_INVALID_PARAM;
-
-	return AVC_CTYPE_REJECTED;
+	*code = AVC_CTYPE_REJECTED;
+	return 1;
 }
 
-static uint8_t avrcp_handle_list_attributes(struct avrcp *session,
-				uint8_t transaction, uint16_t *params_len,
-				uint8_t *params, void *user_data)
+static ssize_t avrcp_handle_list_attributes(struct avrcp *session,
+					uint8_t transaction, uint8_t *code,
+					uint16_t params_len, uint8_t *params,
+					void *user_data)
 {
 	DBG("");
 
-	*params_len = 1;
 	params[0] = 0;
+	*code = AVC_CTYPE_STABLE;
 
-	return AVC_CTYPE_STABLE;
+	return 1;
 }
 
-static uint8_t avrcp_handle_get_player_attr_text(struct avrcp *session,
-				uint8_t transaction, uint16_t *params_len,
-				uint8_t *params, void *user_data)
+static ssize_t avrcp_handle_get_player_attr_text(struct avrcp *session,
+					uint8_t transaction, uint8_t *code,
+					uint16_t params_len, uint8_t *params,
+					void *user_data)
 {
 	DBG("");
 
-	*params_len = 1;
 	params[0] = 0;
+	*code = AVC_CTYPE_STABLE;
 
-	return AVC_CTYPE_STABLE;
+	return 1;
 }
 
 static const struct avrcp_control_handler control_handlers[] = {
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 02/16] android/avctp: Make handler return ssize_t
From: Luiz Augusto von Dentz @ 2014-03-02 18:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1393786109-6554-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This makes possible to return errors such as -EAGAIN to indicate the
request would block and a response will be sent asynchronously.
---
 android/avctp.c     | 17 ++++++++++++-----
 android/avctp.h     |  2 +-
 android/avrcp-lib.c |  2 +-
 unit/test-avctp.c   |  2 +-
 4 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/android/avctp.c b/android/avctp.c
index bc1bd80..aa5abc9 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -311,7 +311,7 @@ static gboolean auto_release(gpointer user_data)
 	return FALSE;
 }
 
-static size_t handle_panel_passthrough(struct avctp *session,
+static ssize_t handle_panel_passthrough(struct avctp *session,
 					uint8_t transaction, uint8_t *code,
 					uint8_t *subunit, uint8_t *operands,
 					size_t operand_count, void *user_data)
@@ -402,7 +402,7 @@ done:
 	return operand_count;
 }
 
-static size_t handle_unit_info(struct avctp *session,
+static ssize_t handle_unit_info(struct avctp *session,
 					uint8_t transaction, uint8_t *code,
 					uint8_t *subunit, uint8_t *operands,
 					size_t operand_count, void *user_data)
@@ -428,7 +428,7 @@ static size_t handle_unit_info(struct avctp *session,
 	return operand_count;
 }
 
-static size_t handle_subunit_info(struct avctp *session,
+static ssize_t handle_subunit_info(struct avctp *session,
 					uint8_t transaction, uint8_t *code,
 					uint8_t *subunit, uint8_t *operands,
 					size_t operand_count, void *user_data)
@@ -849,8 +849,9 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 	uint8_t *operands, code, subunit;
 	struct avctp_header *avctp;
 	struct avc_header *avc;
-	int ret, packet_size, operand_count, sock;
+	int packet_size, operand_count, sock;
 	struct avctp_pdu_handler *handler;
+	ssize_t ret;
 
 	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
 		goto failed;
@@ -910,10 +911,16 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 	code = avc->code;
 	subunit = avc->subunit_type;
 
-	packet_size += handler->cb(session, avctp->transaction, &code,
+	ret = handler->cb(session, avctp->transaction, &code,
 					&subunit, operands, operand_count,
 					handler->user_data);
+	if (ret < 0) {
+		if (ret == -EAGAIN)
+			return TRUE;
+		goto failed;
+	}
 
+	packet_size += ret;
 	avc->code = code;
 	avc->subunit_type = subunit;
 
diff --git a/android/avctp.h b/android/avctp.h
index dfa0ca6..2f419a2 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -113,7 +113,7 @@ struct avctp;
 typedef bool (*avctp_passthrough_cb) (struct avctp *session,
 					uint8_t op, bool pressed,
 					void *user_data);
-typedef size_t (*avctp_control_pdu_cb) (struct avctp *session,
+typedef ssize_t (*avctp_control_pdu_cb) (struct avctp *session,
 					uint8_t transaction, uint8_t *code,
 					uint8_t *subunit, uint8_t *operands,
 					size_t operand_count, void *user_data);
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
index 6fed825..cdad6ac 100644
--- a/android/avrcp-lib.c
+++ b/android/avrcp-lib.c
@@ -115,7 +115,7 @@ void avrcp_shutdown(struct avrcp *session)
 	g_free(session);
 }
 
-static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
+static ssize_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
 					uint8_t *code, uint8_t *subunit,
 					uint8_t *operands, size_t operand_count,
 					void *user_data)
diff --git a/unit/test-avctp.c b/unit/test-avctp.c
index be1dfd7..0759731 100644
--- a/unit/test-avctp.c
+++ b/unit/test-avctp.c
@@ -227,7 +227,7 @@ static void execute_context(struct context *context)
 	destroy_context(context);
 }
 
-static size_t handler(struct avctp *session,
+static ssize_t handler(struct avctp *session,
 					uint8_t transaction, uint8_t *code,
 					uint8_t *subunit, uint8_t *operands,
 					size_t operand_count, void *user_data)
-- 
1.8.5.3


^ 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