Commit 75052a55 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

greybus: bundle: add state sysfs file



A bundle has a state file, that is managed by the endo userspace
process.  This file can be written to and any process that is polling on
the file will be woken up and can read the new value.  It's a "cheap"
IPC for programs that are not allowed to do anything other than
read/write to kernel sysfs files.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 1ffc12be
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -113,3 +113,16 @@ KernelVersion: 4.XX
Contact:	Greg Kroah-Hartman <greg@kroah.com>
Description:
		The device id of a Greybus bundle.

What:		/sys/bus/greybus/device/.../state
Date:		October 2015
KernelVersion:	4.XX
Contact:	Greg Kroah-Hartman <greg@kroah.com>
Description:
		A bundle has a state that is managed by the userspace
		Endo process.  This file allows that Endo to signal
		other Android HALs that the state of the bundle has
		changed to a specific value.  When written to, any
		process watching the file will be woken up, and the new
		value can be read. It's a "poor-man's IPC", yes, but
		simplifies the Android userspace code immensely.
+35 −2
Original line number Diff line number Diff line
/*
 * Greybus bundles
 *
 * Copyright 2014 Google Inc.
 * Copyright 2014 Linaro Ltd.
 * Copyright 2014-2015 Google Inc.
 * Copyright 2014-2015 Linaro Ltd.
 *
 * Released under the GPLv2 only.
 */
@@ -31,9 +31,41 @@ static ssize_t class_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(class);

static ssize_t state_show(struct device *dev, struct device_attribute *attr,
			  char *buf)
{
	struct gb_bundle *bundle = to_gb_bundle(dev);

	if (bundle->state == NULL)
		return sprintf(buf, "\n");

	return sprintf(buf, "%s\n", bundle->state);
}

static ssize_t state_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t size)
{
	struct gb_bundle *bundle = to_gb_bundle(dev);

	kfree(bundle->state);
	bundle->state = kzalloc(size + 1, GFP_KERNEL);
	if (!bundle->state)
		return -ENOMEM;

	memcpy(bundle->state, buf, size);

	/* Tell userspace that the file contents changed */
	sysfs_notify(&bundle->dev.kobj, NULL, "state");

	return size;
}
static DEVICE_ATTR_RW(state);


static struct attribute *bundle_attrs[] = {
	&dev_attr_device_id.attr,
	&dev_attr_class.attr,
	&dev_attr_state.attr,
	NULL,
};

@@ -43,6 +75,7 @@ static void gb_bundle_release(struct device *dev)
{
	struct gb_bundle *bundle = to_gb_bundle(dev);

	kfree(bundle->state);
	kfree(bundle);
}

+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ struct gb_bundle {
	u8			class;
	u8			device_id;
	struct list_head	connections;
	u8			*state;

	struct list_head	links;	/* interface->bundles */
};