* [RFC PATCH V2 1/2] introduce ALS sysfs class
@ 2009-08-06 8:31 Zhang Rui
2009-08-06 15:08 ` Bjorn Helgaas
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Zhang Rui @ 2009-08-06 8:31 UTC (permalink / raw)
To: linux-acpi, Linux Kernel Mailing List
Cc: Pavel Machek, Greg KH, Len Brown, Richard Purdie, Matthew Garrett,
Bjorn Helgaas, Valdis.Kletnieks@vt.edu, Zhang, Rui
Introduce ALS sysfs class device.
ALS sysfs class device provides a standard sysfs interface
for Ambient Light Sensor devices.
Only two sysfs I/F are introduced currently.
/sys/class/als/alsX/illuminance:
indicates the amount of light incident upon a specified surface area.
/sys/class/als/alsX/mappings:
exports ambient light illuminance to display luminance mappings
that can be used by an OS to calibrate its ambient light policy
for a given sensor configuration.
The OS can use this information to extrapolate an ALS response curve
- noting that these values may be treated differently depending on the
OS implementation but should be used in some form to calibrate ALS policy.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
Documentation/als/sysfs.txt | 138 ++++++++++++++++++++++
drivers/Kconfig | 2
drivers/Makefile | 1
drivers/als/Kconfig | 10 +
drivers/als/Makefile | 5
drivers/als/als_sys.c | 269 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/als_sys.h | 57 +++++++++
7 files changed, 482 insertions(+)
Index: linux-2.6/drivers/Kconfig
===================================================================
--- linux-2.6.orig/drivers/Kconfig
+++ linux-2.6/drivers/Kconfig
@@ -62,6 +62,8 @@ source "drivers/power/Kconfig"
source "drivers/hwmon/Kconfig"
+source "drivers/als/Kconfig"
+
source "drivers/thermal/Kconfig"
source "drivers/watchdog/Kconfig"
Index: linux-2.6/drivers/Makefile
===================================================================
--- linux-2.6.orig/drivers/Makefile
+++ linux-2.6/drivers/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_PPS) += pps/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
+obj-$(CONFIG_ALS) += als/
obj-$(CONFIG_THERMAL) += thermal/
obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_PHONE) += telephony/
Index: linux-2.6/drivers/als/Kconfig
===================================================================
--- /dev/null
+++ linux-2.6/drivers/als/Kconfig
@@ -0,0 +1,10 @@
+#
+# Ambient Light Sensor sysfs device configuration
+#
+
+menuconfig ALS
+ tristate "Ambient Light Sensor sysfs device"
+ help
+ This framework provides a generic sysfs I/F for Ambient Light
+ Sensor devices.
+ If you want this support, you should say Y or M here.
Index: linux-2.6/drivers/als/Makefile
===================================================================
--- /dev/null
+++ linux-2.6/drivers/als/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for sensor chip drivers.
+#
+
+obj-$(CONFIG_ALS) += als_sys.o
Index: linux-2.6/drivers/als/als_sys.c
===================================================================
--- /dev/null
+++ linux-2.6/drivers/als/als_sys.c
@@ -0,0 +1,269 @@
+/*
+ * als_sys.c - Ambient Light Sensor Sysfs support.
+ *
+ * Copyright (C) 2009 Intel Corp
+ * Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/als_sys.h>
+
+MODULE_AUTHOR("Zhang Rui");
+MODULE_DESCRIPTION("Ambient Light Sensor sysfs support");
+MODULE_LICENSE("GPL");
+
+#define PREFIX "ALS: "
+
+struct als_mapping_item {
+ struct kobject kobj;
+ int index;
+ struct list_head node;
+};
+
+/* sys I/F for Ambient Light Sensor */
+
+#define to_als_device(dev) container_of(dev, struct als_device, device)
+
+static ssize_t
+desc_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct als_device *als = to_als_device(dev);
+
+ return sprintf(buf, "%s\n", als->desc ? als->desc : "N/A");
+}
+
+static ssize_t
+illuminance_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct als_device *als = to_als_device(dev);
+ int illuminance;
+ int result;
+
+ result = als->ops->get_illuminance(als, &illuminance);
+ if (result)
+ return result;
+
+ if (!illuminance)
+ return sprintf(buf, "Illuminance below the supported range\n");
+ else if (illuminance == -1)
+ return sprintf(buf, "Illuminance above the supported range\n");
+ else if (illuminance < -1)
+ return -ERANGE;
+ else
+ return sprintf(buf, "%d\n", illuminance);
+}
+
+static DEVICE_ATTR(desc, 0444, desc_show, NULL);
+static DEVICE_ATTR(illuminance, 0444, illuminance_show, NULL);
+
+#define ATTR(_name, _mode) \
+ struct attribute als_##_name##_attr = { \
+ .name = __stringify(_name), \
+ .mode = _mode, \
+ };
+
+static ATTR(illuminance, 0444);
+static ATTR(adjustment, 0444);
+
+static struct attribute * als_mapping_attrs[] = {
+ &als_illuminance_attr,
+ &als_adjustment_attr,
+ NULL,
+};
+
+static ssize_t show_mapping_info(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct device *dev = container_of(kobj->parent, struct device, kobj);
+ struct als_device *als = to_als_device(dev);
+ int index, illuminance, adjustment;
+ int result;
+
+ if (!sscanf(kobj->name, "mapping%d", &index))
+ return -EINVAL;
+
+ result = als->ops->get_mapping_info(als, index, &illuminance, &adjustment);
+ if (result)
+ return result;
+
+ return sprintf(buf, "%u\n", (attr == &als_illuminance_attr) ? illuminance : adjustment);
+}
+
+static struct sysfs_ops als_mapping_info_ops = {
+ .show = show_mapping_info,
+ .store = NULL,
+};
+
+static struct kobj_type als_mapping_ktype = {
+ .sysfs_ops = &als_mapping_info_ops,
+ .default_attrs = als_mapping_attrs,
+};
+
+static void als_release(struct device *dev) {
+ struct als_device *als = to_als_device(dev);
+
+ if (als->desc)
+ kfree(als->desc);
+ kfree(als);
+}
+
+static struct class als_class = {
+ .name = "als",
+ .dev_release = als_release,
+};
+
+/**
+ * als_device_update_mappings - update the ambient light illuminance to
+ * display luminance adjustment mappings
+ */
+int als_device_update_mappings(struct als_device *als)
+{
+ int old_count = als->count;
+ int i;
+ struct als_mapping_item *pos, *next;
+ int result;
+
+ result = als->ops->get_mapping_count(als, &als->count);
+ if (result)
+ return result;
+
+ if (old_count == als->count)
+ return 0;
+
+ if (als->count > old_count)
+ for (i = old_count; i < als->count; i++) {
+ pos = kzalloc(sizeof(struct als_mapping_item), GFP_KERNEL);
+ if (!pos)
+ return -ENOMEM;
+
+ pos->index = i;
+ result = kobject_init_and_add(&pos->kobj, &als_mapping_ktype,
+ &als->device.kobj, "mapping%d", pos->index);
+ if (result)
+ break;
+ }
+ else
+ list_for_each_entry_safe(pos, next, &als->mappings, node) {
+ if (pos->index < als->count)
+ continue;
+ list_del(&pos->node);
+ kobject_put(&pos->kobj);
+ kfree(pos);
+ }
+
+ if (result)
+ als->count = i;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(als_device_update_mappings);
+
+/**
+ * als_device_register - register a new Ambient Light Sensor class device
+ * @ops: standard ALS devices callbacks.
+ * @devdata: device private data.
+ */
+struct als_device *als_device_register(struct als_device_ops *ops,
+ char *desc, void *devdata)
+{
+ struct als_device *als;
+ static int als_id;
+ int result;
+
+ if (!ops || !ops->get_illuminance)
+ return ERR_PTR(-EINVAL);
+
+ als = kzalloc(sizeof(struct als_device), GFP_KERNEL);
+ if (!als)
+ return ERR_PTR(-ENOMEM);
+
+ als->ops = ops;
+ als->device.class = &als_class;
+ als->devdata = devdata;
+ als->id = als_id++;
+ INIT_LIST_HEAD(&als->mappings);
+ if (desc) {
+ als->desc = kzalloc(strlen(desc), GFP_KERNEL);
+ if (!als->desc) {
+ kfree(als);
+ return ERR_PTR(-ENOMEM);
+ }
+ strcpy(als->desc, desc);
+ }
+ dev_set_name(&als->device, "als%d", als->id);
+ result = device_register(&als->device);
+ if (result) {
+ if (als->desc)
+ kfree(als->desc);
+ kfree(als);
+ return ERR_PTR(result);
+ }
+
+ /* sys I/F */
+ result = device_create_file(&als->device, &dev_attr_illuminance);
+ if (result)
+ goto unregister_device;
+
+ result = device_create_file(&als->device, &dev_attr_desc);
+ if (result)
+ goto unregister_device;
+
+ return als;
+
+unregister_device:
+ device_unregister(&als->device);
+ return ERR_PTR(result);
+}
+
+EXPORT_SYMBOL(als_device_register);
+
+/**
+ * als_device_unregister - removes the registered ALS device
+ * @als: the ALS device to remove.
+ */
+void als_device_unregister(struct als_device *als)
+{
+ if (!als)
+ return;
+
+ device_remove_file(&als->device, &dev_attr_desc);
+ device_remove_file(&als->device, &dev_attr_illuminance);
+
+ device_unregister(&als->device);
+ return;
+}
+
+EXPORT_SYMBOL(als_device_unregister);
+
+static int __init als_init(void)
+{
+ return class_register(&als_class);
+}
+
+static void __exit als_exit(void)
+{
+ class_unregister(&als_class);
+}
+
+subsys_initcall(als_init);
+module_exit(als_exit);
Index: linux-2.6/include/linux/als_sys.h
===================================================================
--- /dev/null
+++ linux-2.6/include/linux/als_sys.h
@@ -0,0 +1,57 @@
+/*
+ * als.h ($Revision: 0 $)
+ *
+ * Copyright (C) 2009 Intel Corp
+ * Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * 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; version 2 of the License.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#ifndef __ALS_SYS_H__
+#define __ALS_SYS_H__
+
+#include <linux/device.h>
+
+struct als_device;
+
+struct als_device_ops {
+ int (*get_illuminance) (struct als_device *, int *);
+ int (*get_mapping_count) (struct als_device *, int *);
+ int (*get_mapping_info) (struct als_device *, int, int *, int *);
+};
+
+struct als_mapping {
+ int illuminance;
+ int adjustment;
+};
+
+struct als_device {
+ int id;
+ int illuminance;
+ struct device device;
+ struct als_device_ops *ops;
+ void *devdata;
+ char *desc;
+ int count;
+ struct list_head mappings;
+};
+
+int als_device_update_mappings(struct als_device *als);
+struct als_device *als_device_register(struct als_device_ops *, char *, void *);
+void als_device_unregister(struct als_device *);
+
+#endif /* __ALS_SYS_H__ */
Index: linux-2.6/Documentation/als/sysfs.txt
===================================================================
--- /dev/null
+++ linux-2.6/Documentation/als/sysfs.txt
@@ -0,0 +1,138 @@
+Ambient Light Sensor Sysfs driver How To
+=========================
+
+Written by Zhang Rui <rui.zhang@intel.com>
+
+Updated: 6 August 2009
+
+Copyright (c) 2009 Intel Corporation
+
+0. Introduction
+
+The generic Ambient Light Sensor sysfs provides a standard interface for ALS devices.
+
+User space can use this interface to get the status of the ambient light environment
+the system is currently in, and get the ambient light illuminance to display luminance
+mappings to calibrate its ambient light policy for a given sensor configuration.
+
+An intelligent ALS application can make ambient light decisions based on inputs
+from these ALS attributes and adjust the LVDS brightness levels.
+
+[0-*] denotes any positive number starting from 0
+
+Two acronyms that used in this HOW TO only:
+ALI ambient light illuminace
+DLA display luminance adjustment (or display brightness adjustment)
+
+1. Ambient Light Sensor sysfs driver interface functions
+
+1.1 struct als_device *als_device_register(struct als_device_ops *ops, char *desc, void *devdata)
+
+ This interface function adds a new ALS device to
+ /sys/class/als folder as als[0-*].
+
+ ops: thermal zone device call-backs.
+ .get_illuminance: get the current ALI.
+ .get_mappings_count: get the number of ALI to DLA mappings.
+ .get_mapping_info: get the info of a specified ALI to DLA mapping.
+ desc: a description of the ALS device.
+ devdata:device private data
+
+1.2 void als_device_unregister(struct als_device *als)
+
+ This interface function removes the ALS device.
+ It deletes the corresponding entry form /sys/class/als folder.
+
+1.3 int als_device_update_mappings(struct als_device *als)
+
+ This interface updates the ALI to DLA mappings.
+ This is usually invoked by the native ALS driver when it detects a mapping change.
+
+2. sysfs attributes structure
+
+RO read only value
+RW read/write value
+
+ALS sysfs attributes will be represented under /sys/class/als.
+
+/sys/class/als/als[0-*]:
+ |-----desc: Strings which describes the ALS device
+ |-----illuminance: Current ALI
+ |-----mapping[0-*]:
+ |-----illuminance: ALI threshold when an DLA is needed
+ |-----adjustment: how to do the DLA when the threshold is hit
+
+***********************************
+* Ambient Light Sendor attributes *
+***********************************
+
+desc Strings which descibes the current ALS.
+ This is given by native ALS driver as part of registration.
+ Eg: ACPI ALS driver gives the full pathname of
+ the ALS device in ACPI namespace.
+ RO
+ Required
+
+illuminance Current ALI reported by native ALS driver
+ Unit: lux (lumens per square meter)
+ RO
+ Required
+
+mapping[0-*] represent one item of the ALI to DLA mappings.
+
+mapping[0-*]/illuminance ALI threshold when an DLA is needed
+ RO
+
+mapping[0-*]/adjustment a relative percentages in order simplify the means
+ by which these adjustments are applied in lieu of
+ changes to the user’s display brightness preference.
+ A value of 100 is used to indicate no (0%) display
+ brightness adjustment.
+ Values less than 100 indicate a negative adjustment
+ (dimming); values greater than 100 indicate a positive
+ adjustment (brightening).
+ RO
+
+3. How to implement ALS control in user space
+
+To implement the ALS control, including both ALI detection and Backlight
+adjustment, interactions between backlight driver and als driver are needed.
+It's ugly to implement such a driver in Linux kenrel.
+A user space application is preferred in this case.
+
+Below is a simple example about how to do ALS mangement in user space.
+
+This is the ACPI backlight sysfs I/F
+/sys/class/backlight/acpi_video0:
+ |-----brightness 6
+ |-----actual_brightness 6
+ |-----max_brightness 10
+
+And this is the ACPI ALS sysfs I/F
+/sys/class/als/als0:
+ |-----illuminance 500
+ |-----mapping[0]
+ |-----illuminance 0
+ |-----adjustment 50
+ |-----mapping[1]
+ |-----illuminance 200
+ |-----adjustment 70
+ |-----mapping[2]
+ |-----illuminance 600
+ |-----adjustment 100
+ |-----mapping[3]
+ |-----illuminance 900
+ |-----adjustment 125
+ |-----mapping[4]
+ |-----illuminance 1200
+ |-----adjustment 150
+
+If user thinks that brightness level 6 is good enough for him when ALI is 600,
+he can set brightness 6 as the user’s display brightness preference.
+When user goes to the base-room with the laptop and the ALI changes to 200,
+the ALS application knows that it should do a -25% display brightness
+adjustment, i.e. changes the backlight to 4.
+And when the laptop is used outdoors, where the ALI reaches 1200,
+the ALS application should do a +50% adjustment,
+i.e. run "echo 9 > /sys/class/backlight/acpi_video0/brightness".
+
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH V2 1/2] introduce ALS sysfs class
2009-08-06 8:31 [RFC PATCH V2 1/2] introduce ALS sysfs class Zhang Rui
@ 2009-08-06 15:08 ` Bjorn Helgaas
2009-08-06 18:53 ` Greg KH
2009-08-06 18:56 ` Greg KH
2 siblings, 0 replies; 4+ messages in thread
From: Bjorn Helgaas @ 2009-08-06 15:08 UTC (permalink / raw)
To: Zhang Rui
Cc: linux-acpi, Linux Kernel Mailing List, Pavel Machek, Greg KH,
Len Brown, Richard Purdie, Matthew Garrett,
Valdis.Kletnieks@vt.edu
On Thu, 2009-08-06 at 16:31 +0800, Zhang Rui wrote:
> Introduce ALS sysfs class device.
>
> ALS sysfs class device provides a standard sysfs interface
> for Ambient Light Sensor devices.
>
> Only two sysfs I/F are introduced currently.
> /sys/class/als/alsX/illuminance:
> indicates the amount of light incident upon a specified surface area.
> /sys/class/als/alsX/mappings:
> exports ambient light illuminance to display luminance mappings
> that can be used by an OS to calibrate its ambient light policy
> for a given sensor configuration.
> The OS can use this information to extrapolate an ALS response curve
> - noting that these values may be treated differently depending on the
> OS implementation but should be used in some form to calibrate ALS policy.
>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
> Documentation/als/sysfs.txt | 138 ++++++++++++++++++++++
> drivers/Kconfig | 2
> drivers/Makefile | 1
> drivers/als/Kconfig | 10 +
> drivers/als/Makefile | 5
> drivers/als/als_sys.c | 269 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/als_sys.h | 57 +++++++++
> 7 files changed, 482 insertions(+)
>
> Index: linux-2.6/drivers/Kconfig
> ===================================================================
> --- linux-2.6.orig/drivers/Kconfig
> +++ linux-2.6/drivers/Kconfig
> @@ -62,6 +62,8 @@ source "drivers/power/Kconfig"
>
> source "drivers/hwmon/Kconfig"
>
> +source "drivers/als/Kconfig"
> +
> source "drivers/thermal/Kconfig"
>
> source "drivers/watchdog/Kconfig"
> Index: linux-2.6/drivers/Makefile
> ===================================================================
> --- linux-2.6.orig/drivers/Makefile
> +++ linux-2.6/drivers/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_PPS) += pps/
> obj-$(CONFIG_W1) += w1/
> obj-$(CONFIG_POWER_SUPPLY) += power/
> obj-$(CONFIG_HWMON) += hwmon/
> +obj-$(CONFIG_ALS) += als/
> obj-$(CONFIG_THERMAL) += thermal/
> obj-$(CONFIG_WATCHDOG) += watchdog/
> obj-$(CONFIG_PHONE) += telephony/
> Index: linux-2.6/drivers/als/Kconfig
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/als/Kconfig
> @@ -0,0 +1,10 @@
> +#
> +# Ambient Light Sensor sysfs device configuration
> +#
> +
> +menuconfig ALS
> + tristate "Ambient Light Sensor sysfs device"
> + help
> + This framework provides a generic sysfs I/F for Ambient Light
"interface", not "I/F"
> + Sensor devices.
> + If you want this support, you should say Y or M here.
> Index: linux-2.6/drivers/als/Makefile
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/als/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for sensor chip drivers.
> +#
> +
> +obj-$(CONFIG_ALS) += als_sys.o
> Index: linux-2.6/drivers/als/als_sys.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/als/als_sys.c
> @@ -0,0 +1,269 @@
> +/*
> + * als_sys.c - Ambient Light Sensor Sysfs support.
> + *
> + * Copyright (C) 2009 Intel Corp
> + * Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com>
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * 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; version 2 of the License.
> + *
> + * 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.,
> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/als_sys.h>
> +
> +MODULE_AUTHOR("Zhang Rui");
> +MODULE_DESCRIPTION("Ambient Light Sensor sysfs support");
> +MODULE_LICENSE("GPL");
> +
> +#define PREFIX "ALS: "
> +
> +struct als_mapping_item {
> + struct kobject kobj;
> + int index;
> + struct list_head node;
> +};
> +
> +/* sys I/F for Ambient Light Sensor */
> +
> +#define to_als_device(dev) container_of(dev, struct als_device, device)
> +
> +static ssize_t
> +desc_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct als_device *als = to_als_device(dev);
> +
> + return sprintf(buf, "%s\n", als->desc ? als->desc : "N/A");
> +}
> +
> +static ssize_t
> +illuminance_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct als_device *als = to_als_device(dev);
> + int illuminance;
> + int result;
> +
> + result = als->ops->get_illuminance(als, &illuminance);
> + if (result)
> + return result;
> +
> + if (!illuminance)
> + return sprintf(buf, "Illuminance below the supported range\n");
> + else if (illuminance == -1)
> + return sprintf(buf, "Illuminance above the supported range\n");
> + else if (illuminance < -1)
> + return -ERANGE;
> + else
> + return sprintf(buf, "%d\n", illuminance);
> +}
> +
> +static DEVICE_ATTR(desc, 0444, desc_show, NULL);
> +static DEVICE_ATTR(illuminance, 0444, illuminance_show, NULL);
> +
> +#define ATTR(_name, _mode) \
> + struct attribute als_##_name##_attr = { \
> + .name = __stringify(_name), \
> + .mode = _mode, \
> + };
> +
> +static ATTR(illuminance, 0444);
> +static ATTR(adjustment, 0444);
> +
> +static struct attribute * als_mapping_attrs[] = {
> + &als_illuminance_attr,
> + &als_adjustment_attr,
> + NULL,
> +};
> +
> +static ssize_t show_mapping_info(struct kobject *kobj,
> + struct attribute *attr, char *buf)
> +{
> + struct device *dev = container_of(kobj->parent, struct device, kobj);
> + struct als_device *als = to_als_device(dev);
> + int index, illuminance, adjustment;
> + int result;
> +
> + if (!sscanf(kobj->name, "mapping%d", &index))
> + return -EINVAL;
> +
> + result = als->ops->get_mapping_info(als, index, &illuminance, &adjustment);
> + if (result)
> + return result;
> +
> + return sprintf(buf, "%u\n", (attr == &als_illuminance_attr) ? illuminance : adjustment);
> +}
> +
> +static struct sysfs_ops als_mapping_info_ops = {
> + .show = show_mapping_info,
> + .store = NULL,
> +};
> +
> +static struct kobj_type als_mapping_ktype = {
> + .sysfs_ops = &als_mapping_info_ops,
> + .default_attrs = als_mapping_attrs,
> +};
> +
> +static void als_release(struct device *dev) {
Open brace on next line.
> + struct als_device *als = to_als_device(dev);
> +
> + if (als->desc)
> + kfree(als->desc);
> + kfree(als);
> +}
> +
> +static struct class als_class = {
> + .name = "als",
> + .dev_release = als_release,
> +};
> +
> +/**
> + * als_device_update_mappings - update the ambient light illuminance to
> + * display luminance adjustment mappings
> + */
> +int als_device_update_mappings(struct als_device *als)
> +{
> + int old_count = als->count;
> + int i;
> + struct als_mapping_item *pos, *next;
> + int result;
> +
> + result = als->ops->get_mapping_count(als, &als->count);
> + if (result)
> + return result;
> +
> + if (old_count == als->count)
> + return 0;
> +
> + if (als->count > old_count)
> + for (i = old_count; i < als->count; i++) {
> + pos = kzalloc(sizeof(struct als_mapping_item), GFP_KERNEL);
> + if (!pos)
> + return -ENOMEM;
> +
> + pos->index = i;
> + result = kobject_init_and_add(&pos->kobj, &als_mapping_ktype,
> + &als->device.kobj, "mapping%d", pos->index);
> + if (result)
> + break;
> + }
> + else
> + list_for_each_entry_safe(pos, next, &als->mappings, node) {
> + if (pos->index < als->count)
> + continue;
> + list_del(&pos->node);
> + kobject_put(&pos->kobj);
> + kfree(pos);
> + }
> +
> + if (result)
> + als->count = i;
> +
> + return 0;
> +}
> +
> +EXPORT_SYMBOL(als_device_update_mappings);
> +
> +/**
> + * als_device_register - register a new Ambient Light Sensor class device
> + * @ops: standard ALS devices callbacks.
> + * @devdata: device private data.
> + */
> +struct als_device *als_device_register(struct als_device_ops *ops,
> + char *desc, void *devdata)
> +{
> + struct als_device *als;
> + static int als_id;
> + int result;
> +
> + if (!ops || !ops->get_illuminance)
> + return ERR_PTR(-EINVAL);
I probably wouldn't bother with these null pointer checks.
Your ACPI ALS driver does check for failure, but others may
not. If a broken driver supplies a null pointer here, we'll
oops pretty fast, and the backtrace will show exactly what
the problem is.
> +
> + als = kzalloc(sizeof(struct als_device), GFP_KERNEL);
> + if (!als)
> + return ERR_PTR(-ENOMEM);
> +
> + als->ops = ops;
> + als->device.class = &als_class;
> + als->devdata = devdata;
> + als->id = als_id++;
> + INIT_LIST_HEAD(&als->mappings);
> + if (desc) {
> + als->desc = kzalloc(strlen(desc), GFP_KERNEL);
> + if (!als->desc) {
> + kfree(als);
> + return ERR_PTR(-ENOMEM);
> + }
> + strcpy(als->desc, desc);
> + }
> + dev_set_name(&als->device, "als%d", als->id);
> + result = device_register(&als->device);
> + if (result) {
> + if (als->desc)
> + kfree(als->desc);
> + kfree(als);
> + return ERR_PTR(result);
> + }
> +
> + /* sys I/F */
> + result = device_create_file(&als->device, &dev_attr_illuminance);
> + if (result)
> + goto unregister_device;
> +
> + result = device_create_file(&als->device, &dev_attr_desc);
> + if (result)
> + goto unregister_device;
> +
> + return als;
> +
> +unregister_device:
> + device_unregister(&als->device);
> + return ERR_PTR(result);
> +}
> +
> +EXPORT_SYMBOL(als_device_register);
> +
> +/**
> + * als_device_unregister - removes the registered ALS device
> + * @als: the ALS device to remove.
> + */
> +void als_device_unregister(struct als_device *als)
> +{
> + if (!als)
> + return;
Unnecessary null pointer check.
> +
> + device_remove_file(&als->device, &dev_attr_desc);
> + device_remove_file(&als->device, &dev_attr_illuminance);
> +
> + device_unregister(&als->device);
> + return;
> +}
> +
> +EXPORT_SYMBOL(als_device_unregister);
> +
> +static int __init als_init(void)
> +{
> + return class_register(&als_class);
> +}
> +
> +static void __exit als_exit(void)
> +{
> + class_unregister(&als_class);
> +}
> +
> +subsys_initcall(als_init);
> +module_exit(als_exit);
> Index: linux-2.6/include/linux/als_sys.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6/include/linux/als_sys.h
> @@ -0,0 +1,57 @@
> +/*
> + * als.h ($Revision: 0 $)
> + *
> + * Copyright (C) 2009 Intel Corp
> + * Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com>
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + * 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; version 2 of the License.
> + *
> + * 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.,
> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +
> +#ifndef __ALS_SYS_H__
> +#define __ALS_SYS_H__
> +
> +#include <linux/device.h>
> +
> +struct als_device;
> +
> +struct als_device_ops {
> + int (*get_illuminance) (struct als_device *, int *);
> + int (*get_mapping_count) (struct als_device *, int *);
> + int (*get_mapping_info) (struct als_device *, int, int *, int *);
> +};
> +
> +struct als_mapping {
> + int illuminance;
> + int adjustment;
> +};
> +
> +struct als_device {
> + int id;
> + int illuminance;
> + struct device device;
> + struct als_device_ops *ops;
> + void *devdata;
> + char *desc;
> + int count;
> + struct list_head mappings;
> +};
> +
> +int als_device_update_mappings(struct als_device *als);
> +struct als_device *als_device_register(struct als_device_ops *, char *, void *);
> +void als_device_unregister(struct als_device *);
> +
> +#endif /* __ALS_SYS_H__ */
> Index: linux-2.6/Documentation/als/sysfs.txt
> ===================================================================
> --- /dev/null
> +++ linux-2.6/Documentation/als/sysfs.txt
> @@ -0,0 +1,138 @@
> +Ambient Light Sensor Sysfs driver How To
> +=========================
> +
> +Written by Zhang Rui <rui.zhang@intel.com>
> +
> +Updated: 6 August 2009
> +
> +Copyright (c) 2009 Intel Corporation
> +
> +0. Introduction
> +
> +The generic Ambient Light Sensor sysfs provides a standard interface for ALS devices.
> +
> +User space can use this interface to get the status of the ambient light environment
> +the system is currently in, and get the ambient light illuminance to display luminance
> +mappings to calibrate its ambient light policy for a given sensor configuration.
> +
> +An intelligent ALS application can make ambient light decisions based on inputs
> +from these ALS attributes and adjust the LVDS brightness levels.
> +
> +[0-*] denotes any positive number starting from 0
You might use just "N" instead of "[0-*]", i.e.,
"/sys/class/als/alsN" is a common informal shorthand for
"als0, als1, als2, etc".
> +
> +Two acronyms that used in this HOW TO only:
> +ALI ambient light illuminace
> +DLA display luminance adjustment (or display brightness adjustment)
> +
> +1. Ambient Light Sensor sysfs driver interface functions
> +
> +1.1 struct als_device *als_device_register(struct als_device_ops *ops, char *desc, void *devdata)
> +
> + This interface function adds a new ALS device to
> + /sys/class/als folder as als[0-*].
> +
> + ops: thermal zone device call-backs.
> + .get_illuminance: get the current ALI.
> + .get_mappings_count: get the number of ALI to DLA mappings.
> + .get_mapping_info: get the info of a specified ALI to DLA mapping.
> + desc: a description of the ALS device.
> + devdata:device private data
> +
> +1.2 void als_device_unregister(struct als_device *als)
> +
> + This interface function removes the ALS device.
> + It deletes the corresponding entry form /sys/class/als folder.
> +
> +1.3 int als_device_update_mappings(struct als_device *als)
> +
> + This interface updates the ALI to DLA mappings.
> + This is usually invoked by the native ALS driver when it detects a mapping change.
> +
> +2. sysfs attributes structure
> +
> +RO read only value
> +RW read/write value
> +
> +ALS sysfs attributes will be represented under /sys/class/als.
> +
> +/sys/class/als/als[0-*]:
> + |-----desc: Strings which describes the ALS device
> + |-----illuminance: Current ALI
> + |-----mapping[0-*]:
> + |-----illuminance: ALI threshold when an DLA is needed
> + |-----adjustment: how to do the DLA when the threshold is hit
> +
> +***********************************
> +* Ambient Light Sendor attributes *
> +***********************************
> +
> +desc Strings which descibes the current ALS.
> + This is given by native ALS driver as part of registration.
> + Eg: ACPI ALS driver gives the full pathname of
> + the ALS device in ACPI namespace.
> + RO
> + Required
> +
> +illuminance Current ALI reported by native ALS driver
> + Unit: lux (lumens per square meter)
> + RO
> + Required
> +
> +mapping[0-*] represent one item of the ALI to DLA mappings.
> +
> +mapping[0-*]/illuminance ALI threshold when an DLA is needed
> + RO
> +
> +mapping[0-*]/adjustment a relative percentages in order simplify the means
> + by which these adjustments are applied in lieu of
> + changes to the user’s display brightness preference.
> + A value of 100 is used to indicate no (0%) display
> + brightness adjustment.
> + Values less than 100 indicate a negative adjustment
> + (dimming); values greater than 100 indicate a positive
> + adjustment (brightening).
> + RO
> +
> +3. How to implement ALS control in user space
> +
> +To implement the ALS control, including both ALI detection and Backlight
> +adjustment, interactions between backlight driver and als driver are needed.
> +It's ugly to implement such a driver in Linux kenrel.
s/kenrel/kernel/
> +A user space application is preferred in this case.
> +
> +Below is a simple example about how to do ALS mangement in user space.
s/about/of/
s/mangement/management/
> +
> +This is the ACPI backlight sysfs I/F
> +/sys/class/backlight/acpi_video0:
> + |-----brightness 6
> + |-----actual_brightness 6
> + |-----max_brightness 10
> +
> +And this is the ACPI ALS sysfs I/F
> +/sys/class/als/als0:
> + |-----illuminance 500
> + |-----mapping[0]
> + |-----illuminance 0
> + |-----adjustment 50
> + |-----mapping[1]
> + |-----illuminance 200
> + |-----adjustment 70
> + |-----mapping[2]
> + |-----illuminance 600
> + |-----adjustment 100
> + |-----mapping[3]
> + |-----illuminance 900
> + |-----adjustment 125
> + |-----mapping[4]
> + |-----illuminance 1200
> + |-----adjustment 150
> +
> +If user thinks that brightness level 6 is good enough for him when ALI is 600,
> +he can set brightness 6 as the user’s display brightness preference.
> +When user goes to the base-room with the laptop and the ALI changes to 200,
s/base-room/basement/
> +the ALS application knows that it should do a -25% display brightness
> +adjustment, i.e. changes the backlight to 4.
> +And when the laptop is used outdoors, where the ALI reaches 1200,
> +the ALS application should do a +50% adjustment,
> +i.e. run "echo 9 > /sys/class/backlight/acpi_video0/brightness".
> +
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH V2 1/2] introduce ALS sysfs class
2009-08-06 8:31 [RFC PATCH V2 1/2] introduce ALS sysfs class Zhang Rui
2009-08-06 15:08 ` Bjorn Helgaas
@ 2009-08-06 18:53 ` Greg KH
2009-08-06 18:56 ` Greg KH
2 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2009-08-06 18:53 UTC (permalink / raw)
To: Zhang Rui
Cc: linux-acpi, Linux Kernel Mailing List, Pavel Machek, Len Brown,
Richard Purdie, Matthew Garrett, Bjorn Helgaas,
Valdis.Kletnieks@vt.edu
On Thu, Aug 06, 2009 at 04:31:38PM +0800, Zhang Rui wrote:
>
> Introduce ALS sysfs class device.
>
> ALS sysfs class device provides a standard sysfs interface
> for Ambient Light Sensor devices.
>
> Only two sysfs I/F are introduced currently.
> /sys/class/als/alsX/illuminance:
> indicates the amount of light incident upon a specified surface area.
> /sys/class/als/alsX/mappings:
> exports ambient light illuminance to display luminance mappings
> that can be used by an OS to calibrate its ambient light policy
> for a given sensor configuration.
> The OS can use this information to extrapolate an ALS response curve
> - noting that these values may be treated differently depending on the
> OS implementation but should be used in some form to calibrate ALS policy.
>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
> Documentation/als/sysfs.txt | 138 ++++++++++++++++++++++
This needs to be in Documentation/ABI instead.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH V2 1/2] introduce ALS sysfs class
2009-08-06 8:31 [RFC PATCH V2 1/2] introduce ALS sysfs class Zhang Rui
2009-08-06 15:08 ` Bjorn Helgaas
2009-08-06 18:53 ` Greg KH
@ 2009-08-06 18:56 ` Greg KH
2 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2009-08-06 18:56 UTC (permalink / raw)
To: Zhang Rui
Cc: linux-acpi, Linux Kernel Mailing List, Pavel Machek, Len Brown,
Richard Purdie, Matthew Garrett, Bjorn Helgaas,
Valdis.Kletnieks@vt.edu
On Thu, Aug 06, 2009 at 04:31:38PM +0800, Zhang Rui wrote:
> +#define PREFIX "ALS: "
This is not used.
> + /* sys I/F */
> + result = device_create_file(&als->device, &dev_attr_illuminance);
> + if (result)
> + goto unregister_device;
> +
> + result = device_create_file(&als->device, &dev_attr_desc);
> + if (result)
> + goto unregister_device;
These should be default attributes for the device, that way they get
created before userspace is told the device is there, removing any race
conditions you will have otherwise.
> +
> + return als;
> +
> +unregister_device:
> + device_unregister(&als->device);
> + return ERR_PTR(result);
And you weren't cleaning up the file if the second one failed.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-08-06 18:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-06 8:31 [RFC PATCH V2 1/2] introduce ALS sysfs class Zhang Rui
2009-08-06 15:08 ` Bjorn Helgaas
2009-08-06 18:53 ` Greg KH
2009-08-06 18:56 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).