Commit 9e1565bc authored by Corentin Chary's avatar Corentin Chary Committed by Matthew Garrett
Browse files

eeepc-wmi: add camera and card reader support

parent aafa719d
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -8,3 +8,17 @@ Description:
		    * 0 -> Super Performance Mode
		    * 1 -> High Performance Mode
		    * 2 -> Power Saving Mode

What:		/sys/devices/platform/eeepc-wmi/camera
Date:		Jan 2010
KernelVersion:	2.6.39
Contact:	"Corentin Chary" <corentincj@iksaif.net>
Description:
		Control the camera. 1 means on, 0 means off.

What:		/sys/devices/platform/eeepc-wmi/cardr
Date:		Jan 2010
KernelVersion:	2.6.39
Contact:	"Corentin Chary" <corentincj@iksaif.net>
Description:
		Control the card reader. 1 means on, 0 means off.
+88 −1
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BLUETOOTH	0x00010013
#define EEEPC_WMI_DEVID_WWAN3G		0x00010019
#define EEEPC_WMI_DEVID_BACKLIGHT	0x00050012
#define EEEPC_WMI_DEVID_CAMERA		0x00060013
#define EEEPC_WMI_DEVID_CARDREADER	0x00080013
#define EEEPC_WMI_DEVID_TPDLED		0x00100011

#define EEEPC_WMI_DSTS_STATUS_BIT	0x00000001
@@ -879,6 +881,70 @@ static void eeepc_wmi_notify(u32 value, void *context)
	kfree(obj);
}

/*
 * Sys helpers
 */
static int parse_arg(const char *buf, unsigned long count, int *val)
{
	if (!count)
		return 0;
	if (sscanf(buf, "%i", val) != 1)
		return -EINVAL;
	return count;
}

static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
{
	acpi_status status;
	u32 retval;
	int rv, value;

	value = eeepc_wmi_get_devstate_simple(devid);
	if (value == -ENODEV) /* Check device presence */
		return value;

	rv = parse_arg(buf, count, &value);
	status = eeepc_wmi_set_devstate(devid, value, &retval);

	if (ACPI_FAILURE(status))
		return -EIO;
	return rv;
}

static ssize_t show_sys_wmi(int devid, char *buf)
{
	int value = eeepc_wmi_get_devstate_simple(devid);

	if (value < 0)
		return value;

	return sprintf(buf, "%d\n", value);
}

#define EEEPC_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)			\
	static ssize_t show_##_name(struct device *dev,			\
				    struct device_attribute *attr,	\
				    char *buf)				\
	{								\
		return show_sys_wmi(_cm, buf);				\
	}								\
	static ssize_t store_##_name(struct device *dev,		\
				     struct device_attribute *attr,	\
				     const char *buf, size_t count)	\
	{								\
		return store_sys_wmi(_cm, buf, count);			\
	}								\
	static struct device_attribute dev_attr_##_name = {		\
		.attr = {						\
			.name = __stringify(_name),			\
			.mode = _mode },				\
		.show   = show_##_name,					\
		.store  = store_##_name,				\
	}

EEEPC_WMI_CREATE_DEVICE_ATTR(camera, 0644, EEEPC_WMI_DEVID_CAMERA);
EEEPC_WMI_CREATE_DEVICE_ATTR(cardr, 0644, EEEPC_WMI_DEVID_CARDREADER);

static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{
@@ -904,10 +970,31 @@ static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);

static struct attribute *platform_attributes[] = {
	&dev_attr_cpufv.attr,
	&dev_attr_camera.attr,
	&dev_attr_cardr.attr,
	NULL
};

static mode_t eeepc_sysfs_is_visible(struct kobject *kobj,
				     struct attribute *attr,
				     int idx)
{
	bool supported = true;
	int devid = -1;

	if (attr == &dev_attr_camera.attr)
		devid = EEEPC_WMI_DEVID_CAMERA;
	else if (attr == &dev_attr_cardr.attr)
		devid = EEEPC_WMI_DEVID_CARDREADER;

	if (devid != -1)
		supported = eeepc_wmi_get_devstate_simple(devid) != -ENODEV;

	return supported ? attr->mode : 0;
}

static struct attribute_group platform_attribute_group = {
	.is_visible	= eeepc_sysfs_is_visible,
	.attrs		= platform_attributes
};