Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v2 04/11] android/hal-audio: Add support to open output stream
From: Andrzej Kaczmarek @ 2014-01-15 18:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389809037-11575-1-git-send-email-andrzej.kaczmarek@tieto.com>

This patch adds support to open output stream via Audio IPC.
Since only SBC is supported, we always try to open stream for first
endpoint only which is enough.
---
 android/hal-audio.c | 109 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 88 insertions(+), 21 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 13ae056..2abd92a 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -87,9 +87,23 @@ struct audio_endpoint {
 
 static struct audio_endpoint audio_endpoints[MAX_AUDIO_ENDPOINTS];
 
+enum a2dp_state_t {
+	AUDIO_A2DP_STATE_NONE,
+	AUDIO_A2DP_STATE_STANDBY,
+	AUDIO_A2DP_STATE_SUSPENDED,
+	AUDIO_A2DP_STATE_STARTED
+};
+
+struct a2dp_stream_out {
+	struct audio_stream_out stream;
+
+	struct audio_endpoint *ep;
+	enum a2dp_state_t audio_state;
+};
+
 struct a2dp_audio_dev {
 	struct audio_hw_device dev;
-	struct audio_stream_out *out;
+	struct a2dp_stream_out *out;
 };
 
 static const a2dp_sbc_t sbc_presets[] = {
@@ -374,6 +388,38 @@ static int ipc_close_cmd(uint8_t endpoint_id)
 	return result;
 }
 
+static int ipc_open_stream_cmd(uint8_t endpoint_id,
+					struct audio_preset **caps)
+{
+	char buf[BLUEZ_AUDIO_MTU];
+	struct audio_cmd_open_stream cmd;
+	struct audio_rsp_open_stream *rsp =
+					(struct audio_rsp_open_stream *) &buf;
+	size_t rsp_len = sizeof(buf);
+	int result;
+
+	DBG("");
+
+	if (!caps)
+		return AUDIO_STATUS_FAILED;
+
+	cmd.id = endpoint_id;
+
+	result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM,
+				sizeof(cmd), &cmd, &rsp_len, rsp, NULL);
+
+	if (result == AUDIO_STATUS_SUCCESS) {
+		size_t buf_len = sizeof(struct audio_preset) +
+					rsp->preset[0].len;
+		*caps = malloc(buf_len);
+		memcpy(*caps, &rsp->preset, buf_len);
+	} else {
+		*caps = NULL;
+	}
+
+	return result;
+}
+
 static int register_endpoints(void)
 {
 	struct audio_endpoint *ep = &audio_endpoints[0];
@@ -615,35 +661,56 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 
 {
 	struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
-	struct audio_stream_out *out;
+	struct a2dp_stream_out *out;
+	struct audio_preset *preset;
 
-	out = calloc(1, sizeof(struct audio_stream_out));
+	out = calloc(1, sizeof(struct a2dp_stream_out));
 	if (!out)
 		return -ENOMEM;
 
 	DBG("");
 
-	out->common.get_sample_rate = out_get_sample_rate;
-	out->common.set_sample_rate = out_set_sample_rate;
-	out->common.get_buffer_size = out_get_buffer_size;
-	out->common.get_channels = out_get_channels;
-	out->common.get_format = out_get_format;
-	out->common.set_format = out_set_format;
-	out->common.standby = out_standby;
-	out->common.dump = out_dump;
-	out->common.set_parameters = out_set_parameters;
-	out->common.get_parameters = out_get_parameters;
-	out->common.add_audio_effect = out_add_audio_effect;
-	out->common.remove_audio_effect = out_remove_audio_effect;
-	out->get_latency = out_get_latency;
-	out->set_volume = out_set_volume;
-	out->write = out_write;
-	out->get_render_position = out_get_render_position;
-
-	*stream_out = out;
+	out->stream.common.get_sample_rate = out_get_sample_rate;
+	out->stream.common.set_sample_rate = out_set_sample_rate;
+	out->stream.common.get_buffer_size = out_get_buffer_size;
+	out->stream.common.get_channels = out_get_channels;
+	out->stream.common.get_format = out_get_format;
+	out->stream.common.set_format = out_set_format;
+	out->stream.common.standby = out_standby;
+	out->stream.common.dump = out_dump;
+	out->stream.common.set_parameters = out_set_parameters;
+	out->stream.common.get_parameters = out_get_parameters;
+	out->stream.common.add_audio_effect = out_add_audio_effect;
+	out->stream.common.remove_audio_effect = out_remove_audio_effect;
+	out->stream.get_latency = out_get_latency;
+	out->stream.set_volume = out_set_volume;
+	out->stream.write = out_write;
+	out->stream.get_render_position = out_get_render_position;
+
+	/* TODO: for now we always use endpoint 0 */
+	out->ep = &audio_endpoints[0];
+
+	if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
+		goto fail;
+
+	if (!preset)
+		goto fail;
+
+	/* TODO: initialize codec using received audio_preset */
+
+	free(preset);
+
+	*stream_out = &out->stream;
 	a2dp_dev->out = out;
 
+	out->audio_state = AUDIO_A2DP_STATE_STANDBY;
+
 	return 0;
+
+fail:
+	free(out);
+	*stream_out = NULL;
+	return -EIO;
 }
 
 static void audio_close_output_stream(struct audio_hw_device *dev,
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH v2 03/11] android/hal-audio: Add support to unregister audio endpoints
From: Andrzej Kaczmarek @ 2014-01-15 18:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389809037-11575-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 6aad002..13ae056 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -359,6 +359,21 @@ static int ipc_open_cmd(const struct audio_codec *codec)
 	return rsp.id;
 }
 
+static int ipc_close_cmd(uint8_t endpoint_id)
+{
+	struct audio_cmd_close cmd;
+	int result;
+
+	DBG("");
+
+	cmd.id = endpoint_id;
+
+	result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_CLOSE,
+				sizeof(cmd), &cmd, NULL, NULL, NULL);
+
+	return result;
+}
+
 static int register_endpoints(void)
 {
 	struct audio_endpoint *ep = &audio_endpoints[0];
@@ -380,6 +395,20 @@ static int register_endpoints(void)
 	return AUDIO_STATUS_SUCCESS;
 }
 
+static void unregister_endpoints(void)
+{
+	size_t i;
+
+	for (i = 0; i < MAX_AUDIO_ENDPOINTS; i++) {
+		struct audio_endpoint *ep = &audio_endpoints[i];
+
+		if (ep->id) {
+			ipc_close_cmd(ep->id);
+			memset(ep, 0, sizeof(*ep));
+		}
+	}
+}
+
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 								size_t bytes)
 {
@@ -775,6 +804,8 @@ static void *ipc_handler(void *data)
 		if (register_endpoints() != AUDIO_STATUS_SUCCESS) {
 			error("audio: Failed to register endpoints");
 
+			unregister_endpoints();
+
 			shutdown(audio_sk, SHUT_RDWR);
 			continue;
 		}
@@ -798,6 +829,8 @@ static void *ipc_handler(void *data)
 		pthread_mutex_unlock(&close_mutex);
 	}
 
+	unregister_endpoints();
+
 	info("Closing Audio IPC thread");
 	return NULL;
 }
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH v2 02/11] android/hal-audio: Add support to register audio endpoints
From: Andrzej Kaczmarek @ 2014-01-15 18:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389809037-11575-1-git-send-email-andrzej.kaczmarek@tieto.com>

This patch adds support to register audio enpoints via Audio IPC.
Endpoints are registered based on predefined codecs table and for
each defined codec one endpoint is registered. By default, only
SBC will be supported.
---
 android/hal-audio.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 187 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 354c3cf..6aad002 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -31,6 +31,11 @@
 #include "audio-msg.h"
 #include "hal-log.h"
 #include "hal-msg.h"
+#include "../profiles/audio/a2dp-codecs.h"
+
+static const uint8_t a2dp_src_uuid[] = {
+		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
+		0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
 
 static int listen_sk = -1;
 static int audio_sk = -1;
@@ -40,11 +45,138 @@ static pthread_t ipc_th = 0;
 static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+struct audio_input_config {
+	uint32_t rate;
+	uint32_t channels;
+	audio_format_t format;
+};
+
+static int sbc_get_presets(struct audio_preset *preset, size_t *len);
+
+struct audio_codec {
+	uint8_t type;
+
+	int (*get_presets) (struct audio_preset *preset, size_t *len);
+
+	int (*init) (struct audio_preset *preset, void **codec_data);
+	int (*cleanup) (void *codec_data);
+	int (*get_config) (void *codec_data,
+					struct audio_input_config *config);
+	ssize_t (*write_data) (void *codec_data, const void *buffer,
+				size_t bytes);
+};
+
+static const struct audio_codec audio_codecs[] = {
+	{
+		.type = A2DP_CODEC_SBC,
+
+		.get_presets = sbc_get_presets,
+	}
+};
+
+#define NUM_CODECS (sizeof(audio_codecs) / sizeof(audio_codecs[0]))
+
+#define MAX_AUDIO_ENDPOINTS NUM_CODECS
+
+struct audio_endpoint {
+	uint8_t id;
+	const struct audio_codec *codec;
+	void *codec_data;
+	int fd;
+};
+
+static struct audio_endpoint audio_endpoints[MAX_AUDIO_ENDPOINTS];
+
 struct a2dp_audio_dev {
 	struct audio_hw_device dev;
 	struct audio_stream_out *out;
 };
 
+static const a2dp_sbc_t sbc_presets[] = {
+	{
+		.frequency = SBC_SAMPLING_FREQ_44100 | SBC_SAMPLING_FREQ_48000,
+		.channel_mode = SBC_CHANNEL_MODE_MONO |
+				SBC_CHANNEL_MODE_DUAL_CHANNEL |
+				SBC_CHANNEL_MODE_STEREO |
+				SBC_CHANNEL_MODE_JOINT_STEREO,
+		.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8,
+		.allocation_method = SBC_ALLOCATION_SNR |
+					SBC_ALLOCATION_LOUDNESS,
+		.block_length = SBC_BLOCK_LENGTH_4 | SBC_BLOCK_LENGTH_8 |
+				SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16,
+		.min_bitpool = MIN_BITPOOL,
+		.max_bitpool = MAX_BITPOOL
+	},
+	/* middle quality */
+	{
+		.frequency = SBC_SAMPLING_FREQ_44100,
+		.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO,
+		.subbands = SBC_SUBBANDS_8,
+		.allocation_method = SBC_ALLOCATION_LOUDNESS,
+		.block_length = SBC_BLOCK_LENGTH_16,
+		.min_bitpool = MIN_BITPOOL,
+		.max_bitpool = 35
+	},
+	{
+		.frequency = SBC_SAMPLING_FREQ_48000,
+		.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO,
+		.subbands = SBC_SUBBANDS_8,
+		.allocation_method = SBC_ALLOCATION_LOUDNESS,
+		.block_length = SBC_BLOCK_LENGTH_16,
+		.min_bitpool = MIN_BITPOOL,
+		.max_bitpool = 33
+	},
+	/* high quality */
+	{
+		.frequency = SBC_SAMPLING_FREQ_44100,
+		.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO,
+		.subbands = SBC_SUBBANDS_8,
+		.allocation_method = SBC_ALLOCATION_LOUDNESS,
+		.block_length = SBC_BLOCK_LENGTH_16,
+		.min_bitpool = MIN_BITPOOL,
+		.max_bitpool = 53
+	},
+	{
+		.frequency = SBC_SAMPLING_FREQ_48000,
+		.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO,
+		.subbands = SBC_SUBBANDS_8,
+		.allocation_method = SBC_ALLOCATION_LOUDNESS,
+		.block_length = SBC_BLOCK_LENGTH_16,
+		.min_bitpool = MIN_BITPOOL,
+		.max_bitpool = 51
+	},
+};
+
+static int sbc_get_presets(struct audio_preset *preset, size_t *len)
+{
+	int i;
+	int count;
+	size_t new_len = 0;
+	uint8_t *ptr = (uint8_t *) preset;
+	size_t preset_size = sizeof(*preset) + sizeof(a2dp_sbc_t);
+
+	DBG("");
+
+	count = sizeof(sbc_presets) / sizeof(sbc_presets[0]);
+
+	for (i = 0; i < count; i++) {
+		preset = (struct audio_preset *) ptr;
+
+		if (new_len + preset_size > *len)
+			break;
+
+		preset->len = sizeof(a2dp_sbc_t);
+		memcpy(preset->data, &sbc_presets[i], preset->len);
+
+		new_len += preset_size;
+		ptr += preset_size;
+	}
+
+	*len = new_len;
+
+	return i;
+}
+
 static void audio_ipc_cleanup(void)
 {
 	if (audio_sk >= 0) {
@@ -200,6 +332,54 @@ failed:
 	return AUDIO_STATUS_FAILED;
 }
 
+static int ipc_open_cmd(const struct audio_codec *codec)
+{
+	uint8_t buf[BLUEZ_AUDIO_MTU];
+	struct audio_cmd_open *cmd = (struct audio_cmd_open *) buf;
+	struct audio_rsp_open rsp;
+	size_t cmd_len = sizeof(buf) - sizeof(*cmd);
+	size_t rsp_len = sizeof(rsp);
+	int result;
+
+	DBG("");
+
+	memcpy(cmd->uuid, a2dp_src_uuid, sizeof(a2dp_src_uuid));
+
+	cmd->codec = codec->type;
+	cmd->presets = codec->get_presets(cmd->preset, &cmd_len);
+
+	cmd_len += sizeof(*cmd);
+
+	result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN, cmd_len, cmd,
+				&rsp_len, &rsp, NULL);
+
+	if (result != AUDIO_STATUS_SUCCESS)
+		return 0;
+
+	return rsp.id;
+}
+
+static int register_endpoints(void)
+{
+	struct audio_endpoint *ep = &audio_endpoints[0];
+	size_t i;
+
+	for (i = 0; i < NUM_CODECS; i++, ep++) {
+		const struct audio_codec *codec = &audio_codecs[i];
+
+		ep->id = ipc_open_cmd(codec);
+
+		if (!ep->id)
+			return AUDIO_STATUS_FAILED;
+
+		ep->codec = codec;
+		ep->codec_data = NULL;
+		ep->fd = -1;
+	}
+
+	return AUDIO_STATUS_SUCCESS;
+}
+
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 								size_t bytes)
 {
@@ -592,6 +772,13 @@ static void *ipc_handler(void *data)
 
 		DBG("Audio IPC: Connected");
 
+		if (register_endpoints() != AUDIO_STATUS_SUCCESS) {
+			error("audio: Failed to register endpoints");
+
+			shutdown(audio_sk, SHUT_RDWR);
+			continue;
+		}
+
 		memset(&pfd, 0, sizeof(pfd));
 		pfd.fd = audio_sk;
 		pfd.events = POLLHUP | POLLERR | POLLNVAL;
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH v2 01/11] android/hal-audio: Add audio_ipc_cmd
From: Andrzej Kaczmarek @ 2014-01-15 18:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1389809037-11575-1-git-send-email-andrzej.kaczmarek@tieto.com>

From: Lukasz Rymanowski <lukasz.rymanowski@tieto.com>

Add function to handle send/receive on audio_sk.
---
 android/Makefile.am |   1 +
 android/hal-audio.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

diff --git a/android/Makefile.am b/android/Makefile.am
index 7806f79..e09f967 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -120,6 +120,7 @@ android_android_tester_LDFLAGS = -pthread -ldl
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
 android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
+					android/hal-msg.h \
 					android/hal-audio.c \
 					android/hardware/audio.h \
 					android/hardware/audio_effect.h \
diff --git a/android/hal-audio.c b/android/hal-audio.c
index c51b065..354c3cf 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -30,6 +30,7 @@
 
 #include "audio-msg.h"
 #include "hal-log.h"
+#include "hal-msg.h"
 
 static int listen_sk = -1;
 static int audio_sk = -1;
@@ -37,6 +38,7 @@ static bool close_thread = false;
 
 static pthread_t ipc_th = 0;
 static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 struct a2dp_audio_dev {
 	struct audio_hw_device dev;
@@ -51,6 +53,153 @@ static void audio_ipc_cleanup(void)
 	}
 }
 
+static int audio_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len,
+			void *param, size_t *rsp_len, void *rsp, int *fd)
+{
+	ssize_t ret;
+	struct msghdr msg;
+	struct iovec iv[2];
+	struct hal_hdr cmd;
+	char cmsgbuf[CMSG_SPACE(sizeof(int))];
+	struct hal_status s;
+	size_t s_len = sizeof(s);
+
+	if (audio_sk < 0) {
+		error("audio: Invalid cmd socket passed to audio_ipc_cmd");
+		goto failed;
+	}
+
+	if (!rsp || !rsp_len) {
+		memset(&s, 0, s_len);
+		rsp_len = &s_len;
+		rsp = &s;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.service_id = service_id;
+	cmd.opcode = opcode;
+	cmd.len = len;
+
+	iv[0].iov_base = &cmd;
+	iv[0].iov_len = sizeof(cmd);
+
+	iv[1].iov_base = param;
+	iv[1].iov_len = len;
+
+	msg.msg_iov = iv;
+	msg.msg_iovlen = 2;
+
+	pthread_mutex_lock(&sk_mutex);
+
+	ret = sendmsg(audio_sk, &msg, 0);
+	if (ret < 0) {
+		error("audio: Sending command failed:%s", strerror(errno));
+		pthread_mutex_unlock(&sk_mutex);
+		goto failed;
+	}
+
+	/* socket was shutdown */
+	if (ret == 0) {
+		error("audio: Command socket closed");
+		goto failed;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&cmd, 0, sizeof(cmd));
+
+	iv[0].iov_base = &cmd;
+	iv[0].iov_len = sizeof(cmd);
+
+	iv[1].iov_base = rsp;
+	iv[1].iov_len = *rsp_len;
+
+	msg.msg_iov = iv;
+	msg.msg_iovlen = 2;
+
+	if (fd) {
+		memset(cmsgbuf, 0, sizeof(cmsgbuf));
+		msg.msg_control = cmsgbuf;
+		msg.msg_controllen = sizeof(cmsgbuf);
+	}
+
+	ret = recvmsg(audio_sk, &msg, 0);
+	if (ret < 0) {
+		error("audio: Receiving command response failed:%s",
+							strerror(errno));
+		pthread_mutex_unlock(&sk_mutex);
+		goto failed;
+	}
+
+	pthread_mutex_unlock(&sk_mutex);
+
+	if (ret < (ssize_t) sizeof(cmd)) {
+		error("audio: Too small response received(%zd bytes)", ret);
+		goto failed;
+	}
+
+	if (cmd.service_id != service_id) {
+		error("audio: Invalid service id (%u vs %u)", cmd.service_id,
+								service_id);
+		goto failed;
+	}
+
+	if (ret != (ssize_t) (sizeof(cmd) + cmd.len)) {
+		error("audio: Malformed response received(%zd bytes)", ret);
+		goto failed;
+	}
+
+	if (cmd.opcode != opcode && cmd.opcode != AUDIO_OP_STATUS) {
+		error("audio: Invalid opcode received (%u vs %u)",
+						cmd.opcode, opcode);
+		goto failed;
+	}
+
+	if (cmd.opcode == AUDIO_OP_STATUS) {
+		struct hal_status *s = rsp;
+
+		if (sizeof(*s) != cmd.len) {
+			error("audio: Invalid status length");
+			goto failed;
+		}
+
+		if (s->code == AUDIO_STATUS_SUCCESS) {
+			error("audio: Invalid success status response");
+			goto failed;
+		}
+
+		return s->code;
+	}
+
+	/* Receive auxiliary data in msg */
+	if (fd) {
+		struct cmsghdr *cmsg;
+
+		*fd = -1;
+
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level == SOL_SOCKET
+					&& cmsg->cmsg_type == SCM_RIGHTS) {
+				memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
+				break;
+			}
+		}
+	}
+
+	if (rsp_len)
+		*rsp_len = cmd.len;
+
+	return AUDIO_STATUS_SUCCESS;
+
+failed:
+	/* Some serious issue happen on IPC - recover */
+	shutdown(audio_sk, SHUT_RDWR);
+	audio_sk = -1;
+	return AUDIO_STATUS_FAILED;
+}
+
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 								size_t bytes)
 {
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH v2 00/11] Audio HAL implementation
From: Andrzej Kaczmarek @ 2014-01-15 18:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

Hi,

changes v1 -> v2
- fixed comments from Luiz
- removed "codec_" prefix from function related to SBC codec
- additional patch to implement set_parameters for audio device
  (A2dpSuspend is initialized this way)
- changes dummy buffer size to 20*512 which is inline with Bluedroid
  (AudioFlinger does crash when closing output stream when set to 512)


Andrzej Kaczmarek (10):
  android/hal-audio: Add support to register audio endpoints
  android/hal-audio: Add support to unregister audio endpoints
  android/hal-audio: Add support to open output stream
  android/hal-audio: Add support to close output stream
  android/hal-audio: Add support to resume output stream
  android/hal-audio: Add support to suspend output stream
  android/hal-audio: Handle audio preset from stream
  android/hal-audio: Fix module loading
  android/hal-audio: Fix AudioFlinger crash
  android/hal-audio: Implement set_parameters for device

Lukasz Rymanowski (1):
  android/hal-audio: Add audio_ipc_cmd

 android/Makefile.am |   1 +
 android/hal-audio.c | 729 +++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 696 insertions(+), 34 deletions(-)

-- 
1.8.5.2


^ permalink raw reply

* Re: [PATCHv3 0/8] IPC negative tester
From: Szymon Janc @ 2014-01-15 16:04 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Wednesday 15 of January 2014 13:42:29 Jakub Tyszkowski wrote:
> Following patchset adds IPC negative tester framework with few test cases
> checking IPC's behaviour on daemon side. Expected daemon's behaviour is to
> shut down gracefully in case of receiving invalid IPC data.
> 
> v2 changes:
>   * fixed few indentation issues
>   * fixed missing __attribute__((packed))
>   * fixed amount of data written for 'malformed data' test case
>   * fixed opcode for 'invalid service' test case
>   * added patch(8) with more 'malformed data' cases
> 
> v3 changes:
>   * changed license to GPL
>   * changed 'ipc-negative-tester' name to 'ipc-tester'
> 
> Jakub Tyszkowski (8):
>   android/ipc-tester: Skeleton for ipc negative tester
>   android/ipc-tester: Run daemon in separate process
>   android/ipc-tester: Add IPC initialization
>   android/ipc-tester: Add daemon shutdown handler
>   android/ipc-tester: Add sending test data with ipc
>   android/ipc-tester: Register services
>   android/ipc-tester: Add basic test cases for IPC's daemon site
>   androi/ipc-tester: Add more cases for malformed data
> 
>  .gitignore           |   1 +
>  android/Makefile.am  |  17 ++
>  android/ipc-tester.c | 727 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 745 insertions(+)
>  create mode 100644 android/ipc-tester.c
> 
> --
> 1.8.5.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Please send V4 with changes we discussed off-line.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [PATCH 01/12] android/tester: Add set device FRIENDLY_NAME prop success test case
From: Szymon Janc @ 2014-01-15 13:24 UTC (permalink / raw)
  To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

Hi Grzegorz,

On Wednesday 15 of January 2014 13:16:57 Grzegorz Kolodziejczyk wrote:
> This adds set device FRIENDLY NAME property success test case.
> ---
>  android/android-tester.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)
> 
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 030111b..27f436f 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -653,6 +653,20 @@ static void remote_discovery_state_changed_cb(bt_discovery_state_t state)
>  	}
>  }
>  
> +static void remote_setprop_disc_state_changed_cb(bt_discovery_state_t state)
> +{
> +	struct test_data *data = tester_get_data();
> +
> +	if (state == BT_DISCOVERY_STARTED && data->cb_count == 4) {
> +		data->cb_count--;
> +		return;
> +	}
> +	if (state == BT_DISCOVERY_STOPPED) {
> +		data->cb_count--;
> +		check_cb_count();
> +	}
> +}
> +
>  static void discovery_state_changed_cb(bt_discovery_state_t state)
>  {
>  	struct test_data *data = tester_get_data();
> @@ -758,6 +772,27 @@ static void remote_get_property_device_found_cb(int num_properties,
>  	check_expected_status(status);
>  }
>  
> +static void remote_setprop_device_found_cb(int num_properties,
> +						bt_property_t *properties)
> +{
> +	struct test_data *data = tester_get_data();
> +	const struct generic_data *test = data->test_data;
> +	bt_status_t status;
> +	uint8_t *bdaddr = (uint8_t *)hciemu_get_client_bdaddr(data->hciemu);
> +	bt_bdaddr_t remote_addr;
> +
> +	const bt_property_t prop = test->expected_properties[0].prop;
> +
> +	bdaddr2android((const bdaddr_t *)bdaddr, &remote_addr.address);
> +
> +	if (data->cb_count == 3)
> +		data->cb_count--;
> +
> +	status = data->if_bluetooth->set_remote_device_property(&remote_addr,
> +									&prop);
> +	check_expected_status(status);
> +}
> +
>  static void device_found_cb(int num_properties, bt_property_t *properties)
>  {
>  	struct test_data *data = tester_get_data();
> @@ -803,6 +838,29 @@ static void remote_test_device_properties_cb(bt_status_t status,
>  		check_expected_property(properties[i]);
>  }
>  
> +static void remote_setprop_device_properties_cb(bt_status_t status,
> +				bt_bdaddr_t *bd_addr, int num_properties,
> +				bt_property_t *properties)
> +{
> +	int i;
> +	struct test_data *data = tester_get_data();
> +	const struct generic_data *test = data->test_data;
> +	uint8_t *bdaddr = (uint8_t *)hciemu_get_client_bdaddr(data->hciemu);
> +	bt_bdaddr_t remote_addr;
> +	const bt_property_t prop = test->expected_properties[1].prop;
> +
> +	for (i = 0; i < num_properties; i++)
> +		check_expected_property(properties[i]);
> +
> +	if (g_slist_length(data->expected_properties_list) == 1) {
> +		bdaddr2android((const bdaddr_t *)bdaddr, &remote_addr.address);
> +		data->cb_count--;
> +		check_cb_count();
> +		data->if_bluetooth->get_remote_device_property(&remote_addr,
> +								prop.type);
> +	}
> +}
> +
>  static void remote_device_properties_cb(bt_status_t status,
>  				bt_bdaddr_t *bd_addr, int num_properties,
>  				bt_property_t *properties)
> @@ -1596,6 +1654,33 @@ static const struct generic_data bt_dev_getprop_fname_fail_test = {
>  	.expected_adapter_status = BT_STATUS_FAIL,
>  };
>  
> +static const char remote_setprop_fname_val[] = "set_fname_test";
> +
> +static struct priority_property remote_setprop_fname_props[] = {
> +	{
> +	.prop.type = BT_PROPERTY_REMOTE_FRIENDLY_NAME,
> +	.prop.val = &remote_setprop_fname_val,
> +	.prop.len = sizeof(remote_setprop_fname_val) - 1,
> +	},
> +	{
> +	.prop.type = BT_PROPERTY_REMOTE_FRIENDLY_NAME,
> +	.prop.val = &remote_setprop_fname_val,
> +	.prop.len = sizeof(remote_setprop_fname_val) - 1,
> +	},
> +};
> +
> +static const struct generic_data bt_dev_setprop_fname_success_test = {
> +	.expected_hal_cb.discovery_state_changed_cb =
> +					remote_setprop_disc_state_changed_cb,
> +	.expected_hal_cb.device_found_cb = remote_setprop_device_found_cb,
> +	.expected_hal_cb.remote_device_properties_cb =
> +					remote_setprop_device_properties_cb,
> +	.expected_cb_count = 4,
> +	.expected_properties_num = 2,
> +	.expected_properties = remote_setprop_fname_props,
> +	.expected_adapter_status = BT_STATUS_SUCCESS,
> +};
> +
>  static bt_callbacks_t bt_callbacks = {
>  	.size = sizeof(bt_callbacks),
>  	.adapter_state_changed_cb = adapter_state_changed_cb,
> @@ -2235,6 +2320,15 @@ static void test_dev_getprop_fname_fail(const void *test_data)
>  	data->if_bluetooth->start_discovery();
>  }
>  
> +static void test_dev_setprop_fname_success(const void *test_data)
> +{
> +	struct test_data *data = tester_get_data();
> +
> +	init_test_conditions(data);
> +
> +	data->if_bluetooth->start_discovery();
> +}
> +
>  /* Test Socket HAL */
>  
>  static void adapter_socket_state_changed_cb(bt_state_t state)
> @@ -2907,6 +3001,11 @@ int main(int argc, char *argv[])
>  					setup_enabled_adapter,
>  					test_dev_getprop_fname_fail, teardown);
>  
> +	test_bredrle("Bluetooth Device Set FRIENDLY_NAME - Success",
> +				&bt_dev_setprop_fname_success_test,
> +				setup_enabled_adapter,
> +				test_dev_setprop_fname_success, teardown);
> +
>  	test_bredrle("Socket Init", NULL, setup_socket_interface,
>  						test_dummy, teardown);
>  
> 

All patches applied, thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [PATCH BlueZ] android/A2DP: Change to connected state when a transport open
From: Luiz Augusto von Dentz @ 2014-01-15 13:06 UTC (permalink / raw)
  To: linux-bluetooth

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

This changes the connected state to be only sent once a transport is
open, before this was done right after the signalling was connected but
this reflect in the audio HAL side attempting to open a stream while
with possible no transport available.
---
 android/a2dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 35ffe46..a5fc652 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -401,8 +401,6 @@ static void signaling_connect_cb(GIOChannel *chan, GError *err,
 		}
 	}
 
-	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
-
 	return;
 
 failed:
@@ -544,6 +542,8 @@ static void transport_connect_cb(GIOChannel *chan, GError *err,
 		g_io_channel_unref(dev->io);
 		dev->io = NULL;
 	}
+
+	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH BlueZ 1/2] android/A2DP: Add handling of incoming transport connection
From: Luiz Augusto von Dentz @ 2014-01-15 12:55 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1389700090-3642-1-git-send-email-luiz.dentz@gmail.com>

Hi,

On Tue, Jan 14, 2014 at 1:48 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds handling of incoming transport connection attempt.
> ---
>  android/a2dp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 60 insertions(+), 4 deletions(-)
>
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 9f3164a..aab0940 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -477,6 +477,60 @@ static const struct ipc_handler cmd_handlers[] = {
>         { bt_a2dp_disconnect, false, sizeof(struct hal_cmd_a2dp_disconnect) },
>  };
>
> +static struct a2dp_setup *find_setup_by_device(struct a2dp_device *dev)
> +{
> +       GSList *l;
> +
> +       for (l = setups; l; l = g_slist_next(l)) {
> +               struct a2dp_setup *setup = l->data;
> +
> +               if (setup->dev == dev)
> +                       return setup;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void transport_connect_cb(GIOChannel *chan, GError *err,
> +                                                       gpointer user_data)
> +{
> +       struct a2dp_device *dev = user_data;
> +       struct a2dp_setup *setup;
> +       uint16_t imtu, omtu;
> +       GError *gerr = NULL;
> +       int fd;
> +
> +       if (err) {
> +               error("%s", err->message);
> +               return;
> +       }
> +
> +       setup = find_setup_by_device(dev);
> +       if (!setup) {
> +               error("Unable to find stream setup");
> +               return;
> +       }
> +
> +       bt_io_get(chan, &gerr,
> +                       BT_IO_OPT_IMTU, &imtu,
> +                       BT_IO_OPT_OMTU, &omtu,
> +                       BT_IO_OPT_INVALID);
> +       if (gerr) {
> +               error("%s", gerr->message);
> +               g_error_free(gerr);
> +               return;
> +       }
> +
> +       fd = g_io_channel_unix_get_fd(chan);
> +
> +       if (!avdtp_stream_set_transport(setup->stream, fd, imtu, omtu)) {
> +               error("avdtp_stream_set_transport: failed");
> +               return;
> +       }
> +
> +       g_io_channel_set_close_on_unref(chan, FALSE);
> +}
> +
>  static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  {
>         struct a2dp_device *dev;
> @@ -501,13 +555,15 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>                 return;
>         }
>
> -       l = g_slist_find_custom(devices, &dst, device_cmp);
> -       if (l)
> -               return;
> -
>         ba2str(&dst, address);
>         DBG("Incoming connection from %s", address);
>
> +       l = g_slist_find_custom(devices, &dst, device_cmp);
> +       if (l) {
> +               transport_connect_cb(chan, err, l->data);
> +               return;
> +       }
> +
>         dev = a2dp_device_new(&dst);
>         signaling_connect_cb(chan, err, dev);
>  }
> --
> 1.8.4.2

Pushed.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCHv3 8/8] androi/ipc-tester: Add more cases for malformed data
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds tests for more types of possible data malformations.
---
 android/ipc-tester.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 72200d8..046b794 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -591,6 +591,48 @@ static const struct generic_data malformed_data = {
 	.num_services = 1,
 };
 
+static const struct generic_data malformed_data2 = {
+	.ipc_data = {
+		/* use proper msg */
+		.buffer = &register_bt_msg,
+		/* but write incomplete */
+		.len = sizeof(register_bt_msg) - 1,
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct malformed_data3_struct {
+	struct regmod_msg valid_msg;
+	int redundant_data;
+}  __attribute__((packed));
+
+static struct malformed_data3_struct malformed_data3_msg = {
+	/* valid register service message */
+	.valid_msg = {
+		.header = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			.opcode = HAL_OP_REGISTER_MODULE,
+			.len = sizeof(struct hal_cmd_register_module),
+			},
+		.cmd = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			},
+	},
+	/* plus redundant data */
+	. redundant_data = 666,
+};
+
+static const struct generic_data malformed_data3 = {
+	.ipc_data = {
+		/* use malformed msg */
+		.buffer = &malformed_data3_msg,
+		.len = sizeof(malformed_data3_msg),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
 struct hal_hdr enable_unknown_service_hdr = {
 	.service_id = HAL_SERVICE_ID_MAX + 1,
 	.opcode = HAL_OP_REGISTER_MODULE,
@@ -667,6 +709,10 @@ int main(int argc, char *argv[])
 						setup, ipc_send_tc, teardown);
 	test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
 						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data2 (undersized msg)", &malformed_data2,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data3 (oversized msg)", &malformed_data3,
+						setup, ipc_send_tc, teardown);
 	test_bredrle("Invalid service", &enable_unknown_service_data,
 						setup, ipc_send_tc, teardown);
 	test_bredrle("Enable unregistered service",
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 7/8] android/ipc-tester: Add basic test cases for IPC's daemon site
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch add first few test cases checking for proper daemon
termination in case of receiving invalid IPC data.
---
 android/ipc-tester.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 117 insertions(+), 3 deletions(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 5901c78..72200d8 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -546,11 +546,113 @@ static void ipc_send_tc(const void *data)
 							3, user, g_free); \
 	} while (0)
 
-static const struct generic_data dummy_data = {
+struct regmod_msg register_bt_msg = {
+	.header = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		.opcode = HAL_OP_REGISTER_MODULE,
+		.len = sizeof(struct hal_cmd_register_module),
+		},
+	.cmd = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		},
+};
+
+static const struct generic_data to_small_data = {
 	.ipc_data = {
-		.buffer = "",
+		/* valid header and payload */
+		.buffer = &register_bt_msg,
+		/* but write only incomplete header */
 		.len = 1,
 	},
+	.init_services = {},
+	.num_services = 0,
+};
+
+struct regmod_msg register_bt_malformed_size_msg = {
+	.header = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		.opcode = HAL_OP_REGISTER_MODULE,
+		/* wrong payload size declared */
+		.len = sizeof(struct hal_cmd_register_module) - 1,
+		},
+	.cmd = {
+		.service_id = HAL_SERVICE_ID_CORE,
+		},
+};
+
+static const struct generic_data malformed_data = {
+	.ipc_data = {
+		/* use malformed msg - wrong size declared */
+		.buffer = &register_bt_malformed_size_msg,
+		/* but write proper size */
+		.len = sizeof(register_bt_malformed_size_msg),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr enable_unknown_service_hdr = {
+	.service_id = HAL_SERVICE_ID_MAX + 1,
+	.opcode = HAL_OP_REGISTER_MODULE,
+	.len = 0,
+};
+
+static const struct generic_data enable_unknown_service_data = {
+	.ipc_data = {
+		/* enable invalid service */
+		.buffer = &enable_unknown_service_hdr,
+		.len = sizeof(enable_unknown_service_hdr),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr enable_bt_service_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = HAL_OP_ENABLE,
+	.len = 0,
+};
+
+static const struct generic_data enable_unregistered_service_data = {
+	.ipc_data = {
+		/* valid msg */
+		.buffer = &enable_bt_service_hdr,
+		/* send the whole thing */
+		.len = sizeof(enable_bt_service_hdr),
+	},
+	/* but don't register it before enabling */
+	.init_services = {},
+	.num_services = 0,
+};
+
+struct hal_hdr invalid_opcode_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = 0x16,
+	.len = 0,
+};
+
+static const struct generic_data invalid_opcode_data = {
+	.ipc_data = {
+		/* valid msg */
+		.buffer = &invalid_opcode_hdr,
+		/* send the whole thing */
+		.len = sizeof(invalid_opcode_hdr),
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
+struct hal_hdr invalid_msg_size_hdr = {
+	.service_id = HAL_SERVICE_ID_BLUETOOTH,
+	.opcode = HAL_OP_CREATE_BOND,
+	.len = 0,
+};
+
+static const struct generic_data invalid_msg_size_data = {
+	.ipc_data = {
+		.buffer = &invalid_msg_size_hdr,
+		.len = sizeof(invalid_msg_size_hdr),
+	},
 	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
 	.num_services = 1,
 };
@@ -561,7 +663,19 @@ int main(int argc, char *argv[])
 
 	tester_init(&argc, &argv);
 
-	test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
+	test_bredrle("To small data", &to_small_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Malformed data (wrong payload declared)", &malformed_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid service", &enable_unknown_service_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Enable unregistered service",
+					&enable_unregistered_service_data,
+					setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid opcode", &invalid_opcode_data,
+						setup, ipc_send_tc, teardown);
+	test_bredrle("Invalid msg size for opcode", &invalid_msg_size_data,
+						setup, ipc_send_tc, teardown);
 
 	return tester_run();
 }
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 6/8] android/ipc-tester: Register services
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds basic bluetooth service registration during setup procedure.
Without this daemon would reject commands for not registered services.
---
 android/ipc-tester.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 9ffb584..5901c78 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -410,13 +410,53 @@ failed:
 	return false;
 }
 
+struct regmod_msg {
+	struct hal_hdr header;
+	struct hal_cmd_register_module cmd;
+} __attribute__((packed));
+
+static bool setup_module(int service_id)
+{
+	struct hal_hdr response;
+	struct hal_hdr expected_response;
+
+	struct regmod_msg btmodule_msg = {
+		.header = {
+			.service_id = HAL_SERVICE_ID_CORE,
+			.opcode = HAL_OP_REGISTER_MODULE,
+			.len = sizeof(struct hal_cmd_register_module),
+			},
+		.cmd = {
+			.service_id = service_id,
+			},
+	};
+
+	if (write(cmd_sk, &btmodule_msg, sizeof(btmodule_msg)) < 0)
+		goto fail;
+
+	if (read(cmd_sk, &response, sizeof(response)) < 0)
+		goto fail;
+
+	expected_response = btmodule_msg.header;
+	expected_response.len = 0;
+
+	if (memcmp(&response, &expected_response, sizeof(response)) == 0)
+		return true;
+
+fail:
+	tester_warn("Module registration failed.");
+	return false;
+}
+
 static void setup(const void *data)
 {
+	const struct generic_data *generic_data = data;
 	struct test_data *test_data = tester_get_data();
 	int signal_fd[2];
 	char buf[1024];
 	pid_t pid;
 	int len;
+	unsigned int i;
 
 	if (pipe(signal_fd)) {
 		tester_setup_failed();
@@ -460,9 +500,15 @@ static void setup(const void *data)
 		return;
 	}
 
-	/* TODO: register modules */
+	tester_print("Will init %d services.", generic_data->num_services);
+
+	for (i = 0; i < generic_data->num_services; i++)
+		if (!setup_module(generic_data->init_services[i]))
+			tester_setup_failed();
 
 	test_data->setup_done = true;
+
+	tester_setup_complete();
 }
 
 static void teardown(const void *data)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 5/8] android/ipc-tester: Add sending test data with ipc
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds some data structures used to send data with ipc during test setup
and run stage.
---
 android/ipc-tester.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 9be7208..9ffb584 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -55,6 +55,18 @@ struct test_data {
 	bool setup_done;
 };
 
+struct ipc_data {
+	void *buffer;
+	size_t len;
+};
+
+struct generic_data {
+	struct ipc_data ipc_data;
+
+	unsigned int num_services;
+	int init_services[];
+};
+
 #define CONNECT_TIMEOUT (5 * 1000)
 #define SERVICE_NAME "bluetoothd"
 
@@ -467,6 +479,13 @@ static void teardown(const void *data)
 
 static void ipc_send_tc(const void *data)
 {
+	const struct generic_data *generic_data = data;
+	const struct ipc_data *ipc_data = &generic_data->ipc_data;
+
+	if (ipc_data->len) {
+		if (write(cmd_sk, ipc_data->buffer, ipc_data->len) < 0)
+			tester_test_failed();
+	}
 }
 
 #define test_bredrle(name, data, test_setup, test, test_teardown) \
@@ -481,13 +500,22 @@ static void ipc_send_tc(const void *data)
 							3, user, g_free); \
 	} while (0)
 
+static const struct generic_data dummy_data = {
+	.ipc_data = {
+		.buffer = "",
+		.len = 1,
+	},
+	.init_services = {HAL_SERVICE_ID_BLUETOOTH},
+	.num_services = 1,
+};
+
 int main(int argc, char *argv[])
 {
 	snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
 
 	tester_init(&argc, &argv);
 
-	test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+	test_bredrle("Test Dummy", &dummy_data, setup, ipc_send_tc, teardown);
 
 	return tester_run();
 }
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 4/8] android/ipc-tester: Add daemon shutdown handler
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

Handle daemon shutdown asynchronously.
---
 android/ipc-tester.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index b76be32..9be7208 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -52,6 +52,7 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	pid_t bluetoothd_pid;
+	bool setup_done;
 };
 
 #define CONNECT_TIMEOUT (5 * 1000)
@@ -359,6 +360,44 @@ static void cleanup_ipc(void)
 	cmd_sk = -1;
 }
 
+static gboolean check_for_daemon(gpointer user_data)
+{
+	int status;
+	struct test_data *data = user_data;
+
+	if ((waitpid(data->bluetoothd_pid, &status, WNOHANG))
+							!= data->bluetoothd_pid)
+		return true;
+
+	if (WIFEXITED(status)) {
+		tester_test_passed();
+	} else if (WIFSIGNALED(status)) {
+		switch (WTERMSIG(status)) {
+		case SIGTERM:
+			if (data->setup_done)
+				tester_test_passed();
+			else
+				tester_setup_failed();
+			break;
+		case SIGSEGV:
+			tester_warn("Daemon died with segmentation fault");
+			goto failed;
+		default:
+			tester_warn("Bad signal received %d", status);
+			goto failed;
+		}
+	}
+
+	return true;
+
+failed:
+	if (data->setup_done)
+		tester_test_failed();
+	else
+		tester_setup_failed();
+	return false;
+}
+
 static void setup(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
@@ -399,6 +438,10 @@ static void setup(const void *data)
 		tester_setup_failed();
 		return;
 	}
+
+	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, check_for_daemon, test_data,
+									NULL);
+
 	if (!init_ipc()) {
 		tester_warn("Cannot initialize IPC mechanism!");
 		tester_setup_failed();
@@ -406,6 +449,8 @@ static void setup(const void *data)
 	}
 
 	/* TODO: register modules */
+
+	test_data->setup_done = true;
 }
 
 static void teardown(const void *data)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 3/8] android/ipc-tester: Add IPC initialization
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds IPC mechanism initialization.
The deamon is being started and IPC socket connection is established.
---
 android/ipc-tester.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index d920ccf..b76be32 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -23,6 +23,8 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
+#include <poll.h>
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -38,6 +40,8 @@
 #include "src/shared/mgmt.h"
 #include "src/shared/hciemu.h"
 
+#include "hal-msg.h"
+#include <cutils/properties.h>
 
 #define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
 #define EMULATOR_SIGNAL "emulator_started"
@@ -50,8 +54,14 @@ struct test_data {
 	pid_t bluetoothd_pid;
 };
 
+#define CONNECT_TIMEOUT (5 * 1000)
+#define SERVICE_NAME "bluetoothd"
+
 static char exec_dir[PATH_MAX + 1];
 
+static int cmd_sk = -1;
+static int notif_sk = -1;
+
 static void read_info_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -246,6 +256,109 @@ failed:
 	close(fd);
 }
 
+static int accept_connection(int sk)
+{
+	int err;
+	struct pollfd pfd;
+	int new_sk;
+
+	memset(&pfd, 0 , sizeof(pfd));
+	pfd.fd = sk;
+	pfd.events = POLLIN;
+
+	err = poll(&pfd, 1, CONNECT_TIMEOUT);
+	if (err < 0) {
+		err = errno;
+		tester_warn("Failed to poll: %d (%s)", err, strerror(err));
+		return -errno;
+	}
+
+	if (err == 0) {
+		tester_warn("bluetoothd connect timeout");
+		return -errno;
+	}
+
+	new_sk = accept(sk, NULL, NULL);
+	if (new_sk < 0) {
+		err = errno;
+		tester_warn("Failed to accept socket: %d (%s)",
+							err, strerror(err));
+		return -errno;
+	}
+
+	return new_sk;
+}
+
+static bool init_ipc(void)
+{
+	struct sockaddr_un addr;
+
+	int sk;
+	int err;
+
+	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	if (sk < 0) {
+		err = errno;
+		tester_warn("Failed to create socket: %d (%s)", err,
+							strerror(err));
+		return false;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+
+	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
+
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		err = errno;
+		tester_warn("Failed to bind socket: %d (%s)", err,
+								strerror(err));
+		close(sk);
+		return false;
+	}
+
+	if (listen(sk, 2) < 0) {
+		err = errno;
+		tester_warn("Failed to listen on socket: %d (%s)", err,
+								strerror(err));
+		close(sk);
+		return false;
+	}
+
+	/* Start Android Bluetooth daemon service */
+	if (property_set("ctl.start", SERVICE_NAME) < 0) {
+		tester_warn("Failed to start service %s", SERVICE_NAME);
+		close(sk);
+		return false;
+	}
+
+	cmd_sk = accept_connection(sk);
+	if (cmd_sk < 0) {
+		close(sk);
+		return false;
+	}
+
+	notif_sk = accept_connection(sk);
+	if (notif_sk < 0) {
+		close(sk);
+		close(cmd_sk);
+		cmd_sk = -1;
+		return false;
+	}
+
+	tester_print("bluetoothd connected");
+
+	close(sk);
+
+	return true;
+}
+
+static void cleanup_ipc(void)
+{
+	close(cmd_sk);
+	cmd_sk = -1;
+}
+
 static void setup(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
@@ -286,12 +399,21 @@ static void setup(const void *data)
 		tester_setup_failed();
 		return;
 	}
+	if (!init_ipc()) {
+		tester_warn("Cannot initialize IPC mechanism!");
+		tester_setup_failed();
+		return;
+	}
+
+	/* TODO: register modules */
 }
 
 static void teardown(const void *data)
 {
 	struct test_data *test_data = tester_get_data();
 
+	cleanup_ipc();
+
 	if (test_data->bluetoothd_pid)
 		waitpid(test_data->bluetoothd_pid, NULL, 0);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 2/8] android/ipc-tester: Run daemon in separate process
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds new process waiting to run daemon when needed.
---
 android/ipc-tester.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index 9a1b4b0..d920ccf 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -21,8 +21,14 @@
  *
  */
 
+#include <stdlib.h>
 #include <unistd.h>
 
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <libgen.h>
 #include <glib.h>
 
 #include "lib/bluetooth.h"
@@ -33,13 +39,19 @@
 #include "src/shared/hciemu.h"
 
 
+#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
+#define EMULATOR_SIGNAL "emulator_started"
+
 struct test_data {
 	struct mgmt *mgmt;
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
+	pid_t bluetoothd_pid;
 };
 
+static char exec_dir[PATH_MAX + 1];
+
 static void read_info_callback(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -168,13 +180,121 @@ static void test_post_teardown(const void *data)
 	test_data->hciemu = NULL;
 }
 
+static void bluetoothd_start(int hci_index)
+{
+	char prg_name[PATH_MAX + 1];
+	char index[8];
+	char *prg_argv[4];
+
+	snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd");
+	snprintf(index, sizeof(index), "%d", hci_index);
+
+	prg_argv[0] = prg_name;
+	prg_argv[1] = "-i";
+	prg_argv[2] = index;
+	prg_argv[3] = NULL;
+
+	if (!tester_use_debug())
+		fclose(stderr);
+
+	execve(prg_argv[0], prg_argv, NULL);
+}
+
+static void emulator(int pipe, int hci_index)
+{
+	static const char SYSTEM_SOCKET_PATH[] = "\0android_system";
+	char buf[1024];
+	struct sockaddr_un addr;
+	struct timeval tv;
+	int fd;
+	ssize_t len;
+
+	fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+	if (fd < 0)
+		goto failed;
+
+	tv.tv_sec = WAIT_FOR_SIGNAL_TIME;
+	tv.tv_usec = 0;
+	setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
+
+	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("Failed to bind system socket");
+		goto failed;
+	}
+
+	len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL));
+
+	if (len != sizeof(EMULATOR_SIGNAL))
+		goto failed;
+
+	memset(buf, 0, sizeof(buf));
+
+	len = read(fd, buf, sizeof(buf));
+	if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
+		goto failed;
+
+	close(pipe);
+	close(fd);
+	bluetoothd_start(hci_index);
+
+failed:
+	close(pipe);
+	close(fd);
+}
+
 static void setup(const void *data)
 {
-	tester_setup_failed();
+	struct test_data *test_data = tester_get_data();
+	int signal_fd[2];
+	char buf[1024];
+	pid_t pid;
+	int len;
+
+	if (pipe(signal_fd)) {
+		tester_setup_failed();
+		return;
+	}
+
+	pid = fork();
+
+	if (pid < 0) {
+		close(signal_fd[0]);
+		close(signal_fd[1]);
+		tester_setup_failed();
+		return;
+	}
+
+	if (pid == 0) {
+		if (!tester_use_debug())
+			fclose(stderr);
+
+		close(signal_fd[0]);
+		emulator(signal_fd[1], test_data->mgmt_index);
+		exit(0);
+	}
+
+	close(signal_fd[1]);
+	test_data->bluetoothd_pid = pid;
+
+	len = read(signal_fd[0], buf, sizeof(buf));
+	if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
+		close(signal_fd[0]);
+		tester_setup_failed();
+		return;
+	}
 }
 
 static void teardown(const void *data)
 {
+	struct test_data *test_data = tester_get_data();
+
+	if (test_data->bluetoothd_pid)
+		waitpid(test_data->bluetoothd_pid, NULL, 0);
+
 	tester_teardown_complete();
 }
 
@@ -196,6 +316,8 @@ static void ipc_send_tc(const void *data)
 
 int main(int argc, char *argv[])
 {
+	snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
+
 	tester_init(&argc, &argv);
 
 	test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 1/8] android/ipc-tester: Skeleton for ipc negative tester
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389789757-16847-1-git-send-email-jakub.tyszkowski@tieto.com>

Add skeleton for ipc negative testing.
---
 .gitignore           |   1 +
 android/Makefile.am  |  17 +++++
 android/ipc-tester.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 222 insertions(+)
 create mode 100644 android/ipc-tester.c

diff --git a/.gitignore b/.gitignore
index ac76fe2..73a68e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -113,4 +113,5 @@ android/system-emulator
 android/bluetoothd
 android/haltest
 android/android-tester
+android/ipc-tester
 android/bluetoothd-snoop
diff --git a/android/Makefile.am b/android/Makefile.am
index 7806f79..67877b3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -119,6 +119,23 @@ android_android_tester_LDFLAGS = -pthread -ldl
 
 plugin_LTLIBRARIES += android/audio.a2dp.default.la
 
+noinst_PROGRAMS += android/ipc-tester
+
+android_ipc_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
+				emulator/bthost.h emulator/bthost.c \
+				src/shared/io.h src/shared/io-glib.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/hciemu.h src/shared/hciemu.c \
+				src/shared/tester.h src/shared/tester.c \
+				android/hal-utils.h android/hal-utils.c \
+				android/ipc-tester.c
+
+android_ipc_tester_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_ipc_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
 android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
 					android/hal-audio.c \
 					android/hardware/audio.h \
diff --git a/android/ipc-tester.c b/android/ipc-tester.c
new file mode 100644
index 0000000..9a1b4b0
--- /dev/null
+++ b/android/ipc-tester.c
@@ -0,0 +1,204 @@
+/*
+ *
+ *  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
+ *
+ */
+
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "src/shared/tester.h"
+#include "src/shared/mgmt.h"
+#include "src/shared/hciemu.h"
+
+
+struct test_data {
+	struct mgmt *mgmt;
+	uint16_t mgmt_index;
+	struct hciemu *hciemu;
+	enum hciemu_type hciemu_type;
+};
+
+static void read_info_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct mgmt_rp_read_info *rp = param;
+	char addr[18];
+	uint16_t manufacturer;
+	uint32_t supported_settings, current_settings;
+
+	tester_print("Read Info callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	ba2str(&rp->bdaddr, addr);
+	manufacturer = btohs(rp->manufacturer);
+	supported_settings = btohl(rp->supported_settings);
+	current_settings = btohl(rp->current_settings);
+
+	tester_print("  Address: %s", addr);
+	tester_print("  Version: 0x%02x", rp->version);
+	tester_print("  Manufacturer: 0x%04x", manufacturer);
+	tester_print("  Supported settings: 0x%08x", supported_settings);
+	tester_print("  Current settings: 0x%08x", current_settings);
+	tester_print("  Class: 0x%02x%02x%02x",
+			rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
+	tester_print("  Name: %s", rp->name);
+	tester_print("  Short name: %s", rp->short_name);
+
+	if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_pre_setup_complete();
+}
+
+static void index_added_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Added callback");
+	tester_print("  Index: 0x%04x", index);
+
+	data->mgmt_index = index;
+
+	mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
+					read_info_callback, NULL, NULL);
+}
+
+static void index_removed_callback(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Index Removed callback");
+	tester_print("  Index: 0x%04x", index);
+
+	if (index != data->mgmt_index)
+		return;
+
+	mgmt_unregister_index(data->mgmt, data->mgmt_index);
+
+	mgmt_unref(data->mgmt);
+	data->mgmt = NULL;
+
+	tester_post_teardown_complete();
+}
+
+static void read_index_list_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+
+	tester_print("Read Index List callback");
+	tester_print("  Status: 0x%02x", status);
+
+	if (status || !param) {
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+					index_added_callback, NULL, NULL);
+
+	mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+					index_removed_callback, NULL, NULL);
+
+	data->hciemu = hciemu_new(data->hciemu_type);
+	if (!data->hciemu) {
+		tester_warn("Failed to setup HCI emulation");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	tester_print("New hciemu instance created");
+}
+
+static void test_pre_setup(const void *data)
+{
+	struct test_data *test_data = tester_get_data();
+
+	if (!tester_use_debug())
+		fclose(stderr);
+
+	test_data->mgmt = mgmt_new_default();
+	if (!test_data->mgmt) {
+		tester_warn("Failed to setup management interface");
+		tester_pre_setup_failed();
+		return;
+	}
+
+	mgmt_send(test_data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+				NULL, read_index_list_callback, NULL, NULL);
+}
+
+static void test_post_teardown(const void *data)
+{
+	struct test_data *test_data = tester_get_data();
+
+	hciemu_unref(test_data->hciemu);
+	test_data->hciemu = NULL;
+}
+
+static void setup(const void *data)
+{
+	tester_setup_failed();
+}
+
+static void teardown(const void *data)
+{
+	tester_teardown_complete();
+}
+
+static void ipc_send_tc(const void *data)
+{
+}
+
+#define test_bredrle(name, data, test_setup, test, test_teardown) \
+	do { \
+		struct test_data *user; \
+		user = g_malloc0(sizeof(struct test_data)); \
+		if (!user) \
+			break; \
+		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
+		tester_add_full(name, data, test_pre_setup, test_setup, \
+				test, test_teardown, test_post_teardown, \
+							3, user, g_free); \
+	} while (0)
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_bredrle("Test Dummy", NULL, setup, ipc_send_tc, teardown);
+
+	return tester_run();
+}
-- 
1.8.5.2


^ permalink raw reply related

* [PATCHv3 0/8] IPC negative tester
From: Jakub Tyszkowski @ 2014-01-15 12:42 UTC (permalink / raw)
  To: linux-bluetooth

Following patchset adds IPC negative tester framework with few test cases
checking IPC's behaviour on daemon side. Expected daemon's behaviour is to
shut down gracefully in case of receiving invalid IPC data.

v2 changes:
  * fixed few indentation issues
  * fixed missing __attribute__((packed))
  * fixed amount of data written for 'malformed data' test case
  * fixed opcode for 'invalid service' test case
  * added patch(8) with more 'malformed data' cases

v3 changes:
  * changed license to GPL
  * changed 'ipc-negative-tester' name to 'ipc-tester'

Jakub Tyszkowski (8):
  android/ipc-tester: Skeleton for ipc negative tester
  android/ipc-tester: Run daemon in separate process
  android/ipc-tester: Add IPC initialization
  android/ipc-tester: Add daemon shutdown handler
  android/ipc-tester: Add sending test data with ipc
  android/ipc-tester: Register services
  android/ipc-tester: Add basic test cases for IPC's daemon site
  androi/ipc-tester: Add more cases for malformed data

 .gitignore           |   1 +
 android/Makefile.am  |  17 ++
 android/ipc-tester.c | 727 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 745 insertions(+)
 create mode 100644 android/ipc-tester.c

--
1.8.5.2


^ permalink raw reply

* [PATCH 12/12] android/tester: Add set device DISCTIMEOUT prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device DISCOVERY TIMEOUT property fail test case.
---
 android/android-tester.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 378d319..6f0e962 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1898,6 +1898,25 @@ static const struct generic_data bt_dev_setprop_bondeddev_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static uint32_t remote_setprop_disctimeout_val = 120;
+
+static struct priority_property remote_setprop_disctimeout_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+	.prop.val = &remote_setprop_disctimeout_val,
+	.prop.len = sizeof(remote_setprop_disctimeout_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_disctimeout_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_disctimeout_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2636,6 +2655,14 @@ static void test_dev_setprop_bondeddev_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_disctimeout_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3363,6 +3390,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_bondeddev_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set DISCOVERY_TIMEOUT - Fail",
+				&bt_dev_setprop_disctimeout_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_disctimeout_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 11/12] android/tester: Add set device BONDED_DEV prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device BONDED DEVICES property fail test case.
---
 android/android-tester.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index e3c39ce..378d319 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1877,6 +1877,27 @@ static const struct generic_data bt_dev_setprop_scanmode_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static bt_bdaddr_t remote_setprop_bondeddev_val = {
+	.address = { 0x00, 0xaa, 0x01, 0x00, 0x00, 0x00 }
+};
+
+static struct priority_property remote_setprop_bondeddev_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+	.prop.val = &remote_setprop_bondeddev_val,
+	.prop.len = sizeof(remote_setprop_bondeddev_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_bondeddev_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_bondeddev_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2606,6 +2627,15 @@ static void test_dev_setprop_scanmode_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_bondeddev_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3328,6 +3358,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_scanmode_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set BONDED_DEVICES - Fail",
+				&bt_dev_setprop_bondeddev_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_bondeddev_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 10/12] android/tester: Add set device SCAN_MODE prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device SCAN MODE property fail test case.
---
 android/android-tester.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 69e477c..e3c39ce 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1858,6 +1858,25 @@ static const struct generic_data bt_dev_setprop_servrec_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static bt_scan_mode_t remote_setprop_scanmode_val = BT_SCAN_MODE_CONNECTABLE;
+
+static struct priority_property remote_setprop_scanmode_props[] = {
+	{
+	.prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE,
+	.prop.val = &remote_setprop_scanmode_val,
+	.prop.len = sizeof(remote_setprop_scanmode_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_scanmode_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_scanmode_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2578,6 +2597,15 @@ static void test_dev_setprop_servrec_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_scanmode_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3295,6 +3323,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_servrec_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set SCAN_MODE - Fail",
+				&bt_dev_setprop_scanmode_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_scanmode_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 09/12] android/tester: Add set device SERVICE_RECORD prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device SERVICE RECORD property fail test case.
---
 android/android-tester.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 06ed997..69e477c 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1835,6 +1835,29 @@ static const struct generic_data bt_dev_setprop_bdaddr_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static bt_service_record_t remote_setprop_servrec_val = {
+	.uuid = { {0x00} },
+	.channel = 12,
+	.name = "bt_name",
+};
+
+static struct priority_property remote_setprop_servrec_props[] = {
+	{
+	.prop.type = BT_PROPERTY_SERVICE_RECORD,
+	.prop.val = &remote_setprop_servrec_val,
+	.prop.len = sizeof(remote_setprop_servrec_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_servrec_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_servrec_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2546,6 +2569,15 @@ static void test_dev_setprop_bdaddr_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_servrec_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3258,6 +3290,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_bdaddr_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set SERVICE_RECORD - Fail",
+				&bt_dev_setprop_servrec_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_servrec_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 08/12] android/tester: Add set device BDADDR prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device BDADDR property fail test case.
---
 android/android-tester.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 3109966..06ed997 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1814,6 +1814,27 @@ static const struct generic_data bt_dev_setprop_timpestamp_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static bt_bdaddr_t remote_setprop_bdaddr_val = {
+	.address = { 0x00, 0xaa, 0x01, 0x00, 0x00, 0x00 }
+};
+
+static struct priority_property remote_setprop_bdaddr_props[] = {
+	{
+	.prop.type = BT_PROPERTY_BDADDR,
+	.prop.val = &remote_setprop_bdaddr_val,
+	.prop.len = sizeof(remote_setprop_bdaddr_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_bdaddr_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_bdaddr_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2516,6 +2537,15 @@ static void test_dev_setprop_timestamp_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_bdaddr_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3223,6 +3253,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_timestamp_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set BDADDR - Fail",
+				&bt_dev_setprop_bdaddr_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_bdaddr_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 07/12] android/tester: Add set device TIMESTAMP prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device TIMESTAMP property fail test case.
---
 android/android-tester.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 81fb1e6..3109966 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1795,6 +1795,25 @@ static const struct generic_data bt_dev_setprop_rssi_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static int32_t remote_setprop_timestamp_val = 0xAB;
+
+static struct priority_property remote_setprop_timestamp_props[] = {
+	{
+	.prop.type = BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP,
+	.prop.val = (&remote_setprop_timestamp_val),
+	.prop.len = sizeof(remote_setprop_timestamp_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_timpestamp_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_timestamp_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2488,6 +2507,15 @@ static void test_dev_setprop_rssi_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_timestamp_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3190,6 +3218,11 @@ int main(int argc, char *argv[])
 				setup_enabled_adapter,
 				test_dev_setprop_rssi_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set TIMESTAMP - Fail",
+				&bt_dev_setprop_timpestamp_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_timestamp_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 06/12] android/tester: Add set device RSSI prop fail test case
From: Grzegorz Kolodziejczyk @ 2014-01-15 12:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389788228-32195-1-git-send-email-grzegorz.kolodziejczyk@tieto.com>

This adds set device RSSI property fail test case.
---
 android/android-tester.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index ecf0594..81fb1e6 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1776,6 +1776,25 @@ static const struct generic_data bt_dev_setprop_tod_fail_test = {
 	.expected_adapter_status = BT_STATUS_FAIL,
 };
 
+static int32_t remote_setprop_rssi_val = -60;
+
+static struct priority_property remote_setprop_rssi_props[] = {
+	{
+	.prop.type = BT_PROPERTY_REMOTE_RSSI,
+	.prop.val = &remote_setprop_rssi_val,
+	.prop.len = sizeof(remote_setprop_rssi_val),
+	},
+};
+
+static const struct generic_data bt_dev_setprop_rssi_fail_test = {
+	.expected_hal_cb.discovery_state_changed_cb =
+					remote_discovery_state_changed_cb,
+	.expected_hal_cb.device_found_cb = remote_setprop_fail_device_found_cb,
+	.expected_cb_count = 3,
+	.expected_properties = remote_setprop_rssi_props,
+	.expected_adapter_status = BT_STATUS_FAIL,
+};
+
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
 	.adapter_state_changed_cb = adapter_state_changed_cb,
@@ -2460,6 +2479,15 @@ static void test_dev_setprop_tod_fail(const void *test_data)
 	data->if_bluetooth->start_discovery();
 }
 
+static void test_dev_setprop_rssi_fail(const void *test_data)
+{
+	struct test_data *data = tester_get_data();
+
+	init_test_conditions(data);
+
+	data->if_bluetooth->start_discovery();
+}
+
 /* Test Socket HAL */
 
 static void adapter_socket_state_changed_cb(bt_state_t state)
@@ -3157,6 +3185,11 @@ int main(int argc, char *argv[])
 					setup_enabled_adapter,
 					test_dev_setprop_tod_fail, teardown);
 
+	test_bredrle("Bluetooth Device Set RSSI - Fail",
+				&bt_dev_setprop_rssi_fail_test,
+				setup_enabled_adapter,
+				test_dev_setprop_rssi_fail, teardown);
+
 	test_bredrle("Socket Init", NULL, setup_socket_interface,
 						test_dummy, teardown);
 
-- 
1.8.5.2


^ 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