/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/socket.h>
#include <sys/un.h>

#include <alsa/asoundlib.h>
#include <alsa/control_external.h>

#include <bluetooth/bluetooth.h>

#include "ipc.h"

#ifdef ENABLE_DEBUG
#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
#else
#define DBG(fmt, arg...)
#endif

#define BLUETOOTH_MINVOL 0
#define BLUETOOTH_MAXVOL 15

struct bluetooth_data {
	snd_ctl_ext_t ext;
	int sock;
};

enum {
	BLUETOOTH_PLAYBACK,
	BLUETOOTH_CAPTURE,
};

static const char *vol_devices[2] = {
	[BLUETOOTH_PLAYBACK]	= "Playback volume",
	[BLUETOOTH_CAPTURE]	= "Capture volume",
};

static void bluetooth_exit(struct bluetooth_data *data)
{
	if (data == NULL)
		return;

	if (data->sock >= 0)
		bt_audio_service_close(data->sock);

	free(data);
}

static void bluetooth_close(snd_ctl_ext_t *ext)
{
	struct bluetooth_data *data = ext->private_data;

	DBG("ext %p", ext);

	bluetooth_exit(data);
}

static int bluetooth_elem_count(snd_ctl_ext_t *ext)
{
	DBG("ext %p", ext);

	return 2;
}

static int bluetooth_elem_list(snd_ctl_ext_t *ext,
				unsigned int offset, snd_ctl_elem_id_t *id)
{
	DBG("ext %p offset %d id %p", ext, offset, id);

	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);

	if (offset > 1)
		return -EINVAL;

	snd_ctl_elem_id_set_name(id, vol_devices[offset]);

	return 0;
}

static snd_ctl_ext_key_t bluetooth_find_elem(snd_ctl_ext_t *ext,
						const snd_ctl_elem_id_t *id)
{
	const char *name = snd_ctl_elem_id_get_name(id);
	int i;

	DBG("ext %p id %p name '%s'", ext, id, name);

	for (i = 0; i < 2; i++)
		if (strcmp(name, vol_devices[i]) == 0)
			return i;

	return SND_CTL_EXT_KEY_NOT_FOUND;
}

static int bluetooth_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
			int *type, unsigned int *acc, unsigned int *count)
{
	DBG("ext %p key %ld", ext, key);

	*type  = SND_CTL_ELEM_TYPE_INTEGER;
	*acc   = SND_CTL_EXT_ACCESS_READWRITE;
	*count = 1;

	return 0;
}

static int bluetooth_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
					long *imin, long *imax, long *istep)
{
	DBG("ext %p key %ld", ext, key);

	*istep = 1;
	*imin  = BLUETOOTH_MINVOL;
	*imax  = BLUETOOTH_MAXVOL;

	return 0;
}

static int bluetooth_send_ctl(struct bluetooth_data *data,
			uint8_t mode, uint8_t key, struct bt_control_rsp *ctl_rsp)
{
	int ret;
	struct bt_control_req *ctl_req = (void *) ctl_rsp;
	const char *type;

	memset(ctl_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
	ctl_req->h.msg_type = BT_CONTROL_REQ;
	ctl_req->mode = mode;
	ctl_req->key = key;

	ret = send(data->sock, ctl_req, BT_AUDIO_IPC_PACKET_SIZE, MSG_NOSIGNAL);
	if (ret <= 0) {
		SYSERR("Unable to request new volume value to server");
		return  -errno;
	}

	ret = recv(data->sock, ctl_rsp, BT_AUDIO_IPC_PACKET_SIZE, 0);
	if (ret <= 0) {
		SNDERR("Unable to receive new volume value from server");
		return  -errno;
	}

	type = bt_audio_strmsg(ctl_rsp->rsp_h.msg_h.msg_type);
	if (!type) {
		SNDERR("Bogus message type %d "
				"received from audio service",
				ctl_rsp->rsp_h.msg_h.msg_type);
		return -EINVAL;
	}

	if (ctl_rsp->rsp_h.msg_h.msg_type != BT_CONTROL_RSP) {
		SNDERR("Unexpected message %s received", type);
		return -EINVAL;
	}

	if (ctl_rsp->rsp_h.posix_errno != 0) {
		SNDERR("BT_CONTROL failed : %s (%d)",
					strerror(ctl_rsp->rsp_h.posix_errno),
					ctl_rsp->rsp_h.posix_errno);
		return -ctl_rsp->rsp_h.posix_errno;
	}

	return 0;
}

static int bluetooth_read_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
								long *value)
{
	struct bluetooth_data *data = ext->private_data;
	int ret;
	char buf[BT_AUDIO_IPC_PACKET_SIZE];
	struct bt_control_rsp *rsp = (void *) buf;

	DBG("ext %p key %ld", ext, key);

	memset(buf, 0, sizeof(buf));
	*value = 0;

	ret = bluetooth_send_ctl(data, key, 0, rsp);
	if (ret < 0)
		goto done;

	*value = rsp->key;
done:
	return ret;
}

static int bluetooth_write_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key,
								long *value)
{
	struct bluetooth_data *data = ext->private_data;
	char buf[BT_AUDIO_IPC_PACKET_SIZE];
	struct bt_control_rsp *rsp = (void *) buf;
	long current;
	int ret, keyvalue;

	DBG("ext %p key %ld", ext, key);

	ret = bluetooth_read_integer(ext, key, &current);
	if (ret < 0)
		return ret;

	if (*value == current)
		return 0;

	while (*value != current) {
		keyvalue = (*value > current) ? BT_CONTROL_KEY_VOL_UP :
				BT_CONTROL_KEY_VOL_DOWN;

		ret = bluetooth_send_ctl(data, key, keyvalue, rsp);
		if (ret < 0)
			break;

		current = keyvalue;
	}

	return ret;
}

static int bluetooth_read_event(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id,
						unsigned int *event_mask)
{
	struct bluetooth_data *data = ext->private_data;
	char buf[BT_AUDIO_IPC_PACKET_SIZE];
	struct bt_control_ind *ind = (void *) buf;
	int ret;
	const char *type;

	DBG("ext %p id %p", ext, id);

	memset(buf, 0, sizeof(buf));

	ret = recv(data->sock, ind, BT_AUDIO_IPC_PACKET_SIZE, MSG_DONTWAIT);
	type = bt_audio_strmsg(ind->h.msg_type);
	if (!type) {
		SNDERR("Bogus message type %d "
				"received from audio service",
				ind->h.msg_type);
		return -EAGAIN;
	}

	if (ind->h.msg_type != BT_CONTROL_IND) {
		SNDERR("Unexpected message %s received", type);
		return -EAGAIN;
	}

	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
	snd_ctl_elem_id_set_name(id, ind->mode == BLUETOOTH_PLAYBACK ?
				vol_devices[BLUETOOTH_PLAYBACK] :
				vol_devices[BLUETOOTH_CAPTURE]);
	*event_mask = SND_CTL_EVENT_MASK_VALUE;

	return 1;
}

static snd_ctl_ext_callback_t bluetooth_callback = {
	.close			= bluetooth_close,
	.elem_count		= bluetooth_elem_count,
	.elem_list		= bluetooth_elem_list,
	.find_elem		= bluetooth_find_elem,
	.get_attribute		= bluetooth_get_attribute,
	.get_integer_info	= bluetooth_get_integer_info,
	.read_integer		= bluetooth_read_integer,
	.write_integer		= bluetooth_write_integer,
	.read_event		= bluetooth_read_event,
};

static int bluetooth_init(struct bluetooth_data *data)
{
	int sk;

	if (!data)
		return -EINVAL;

	memset(data, 0, sizeof(struct bluetooth_data));

	data->sock = -1;

	sk = bt_audio_service_open();
	if (sk < 0)
		return -errno;

	data->sock = sk;

	return 0;
}

SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth)
{
	struct bluetooth_data *data;
	int err;

	DBG("Bluetooth Control plugin");

	data = malloc(sizeof(struct bluetooth_data));
	if (!data) {
		err = -ENOMEM;
		goto error;
	}

	err = bluetooth_init(data);
	if (err < 0)
		goto error;

	data->ext.version = SND_CTL_EXT_VERSION;
	data->ext.card_idx = -1;

	strncpy(data->ext.id, "bluetooth", sizeof(data->ext.id) - 1);
	strncpy(data->ext.driver, "Bluetooth-Audio", sizeof(data->ext.driver) - 1);
	strncpy(data->ext.name, "Bluetooth Audio", sizeof(data->ext.name) - 1);
	strncpy(data->ext.longname, "Bluetooth Audio", sizeof(data->ext.longname) - 1);
	strncpy(data->ext.mixername, "Bluetooth Audio", sizeof(data->ext.mixername) - 1);

	data->ext.callback = &bluetooth_callback;
	data->ext.poll_fd = data->sock;
	data->ext.private_data = data;

	err = snd_ctl_ext_create(&data->ext, name, mode);
	if (err < 0)
		goto error;

	*handlep = data->ext.handle;

	return 0;

error:
	bluetooth_exit(data);

	return err;
}

SND_CTL_PLUGIN_SYMBOL(bluetooth);
