#include <linux/module.h>
#include <linux/slab.h>

#include <avm/hui/button.h>

#include "button.h"

static void button_release(struct kobject *kobj)
{
	struct button *button = to_button_obj(kobj);

	kfree(button);
}

struct button_attribute {
	struct attribute attr;
	ssize_t (*show)(struct button *button, char *buf);
	ssize_t (*store)(struct button *button, const char *buf, size_t count);
};
#define to_button_attr(x) container_of(x, struct button_attribute, attr)

static ssize_t button_attr_show(struct kobject *kobj,
				struct attribute *attribute, char *buf)
{
	struct button_attribute *attr = to_button_attr(attribute);
	struct button *button = to_button_obj(kobj);
	ssize_t ret;

	if (!attr->show)
		return -EIO;

	ret = attr->show(button, buf);

	return ret;
}

static ssize_t button_attr_store(struct kobject *kobj,
				 struct attribute *attribute, const char *buf,
				 size_t count)
{
	struct button_attribute *attr = to_button_attr(attribute);
	struct button *button = to_button_obj(kobj);
	ssize_t ret;

	if (!attr->store)
		return -EIO;

	ret = attr->store(button, buf, count);

	return ret;
}

static const struct sysfs_ops button_sysfs_ops = {
	.show = button_attr_show,
	.store = button_attr_store,
};

static ssize_t action_store(struct button *button, const char *buf,
			    size_t count)
{
	if (sysfs_streq(buf, "up"))
		avm_hui_button_input(button, 0);
	else if (sysfs_streq(buf, "down"))
		avm_hui_button_input(button, 1);
	else
		return -EINVAL;

	return count;
}

static struct button_attribute action_attribute = __ATTR_WO(action);

static struct attribute *button_default_attrs[] = {
	&action_attribute.attr,
	NULL,
};

struct kobj_type button_ktype = {
	.sysfs_ops = &button_sysfs_ops,
	.release = button_release,
	.default_attrs = button_default_attrs,
};