Subject: [PATCH] [acpi driver model] Add basic default sysfs interface for devices - Export HID, UID, and CID list for each device that has them - Interface uses acpi_sysfs_device{,un}register() - Added on device register - Config option added (ACPI_DM_SYSFS), making interface optional Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/Kconfig | 32 +++++++++ drivers/acpi/drivers/core/Makefile | 2 + drivers/acpi/drivers/core/device.c | 14 ++++ drivers/acpi/drivers/core/sysfs.c | 124 ++++++++++++++++++++++++++++++++++++ drivers/acpi/drivers/core/sysfs.h | 28 ++++++++ 5 files changed, 199 insertions(+), 1 deletions(-) create mode 100644 drivers/acpi/drivers/core/sysfs.c create mode 100644 drivers/acpi/drivers/core/sysfs.h applies-to: 2d530b76c9ba1ef4274b52f2e70e99f269f5f93d 58e6f220219b893781dad3dd1c0f39e9495126b1 diff --git a/drivers/acpi/drivers/Kconfig b/drivers/acpi/drivers/Kconfig index 3b09067..e5ea60e 100644 --- a/drivers/acpi/drivers/Kconfig +++ b/drivers/acpi/drivers/Kconfig @@ -33,5 +33,37 @@ config ACPI_DM_DEBUG You probably want to say 'N' here, unless you are developing an extension to the ACPI driver model core, or are debugging it for some reason. + + +config ACPI_DM_SYSFS + bool "Enable sysfs interface for ACPI devices" + depends on ACPI_DM && SYSFS + default y + ---help--- + + This option enables a sysfs configuration interface for + ACPI devices and drivers. By selecting this option, each ACPI + device will export a small number of default files via sysfs + that are added by the ACPI driver model core. These files are + informational only and do not offer any device control. + + In addition, each ACPI driver may export a number of files for + actually controlling the ACPI object and/or device. + + Note that this option controls only the management interface + via regular files in the sysfs hierarchy. ACPI devices and + drivers will appear in the sysfs hierarchy even if this option + is not selected. + + You probably want to say 'Y' here. + + + For more information on sysfs, please see + + Documentation/filesystems/sysfs.txt + + For more information on the interface that each driver exports, + please see the documentation for that driver. + endmenu diff --git a/drivers/acpi/drivers/core/Makefile b/drivers/acpi/drivers/core/Makefile index bef21a0..da56506 100644 --- a/drivers/acpi/drivers/core/Makefile +++ b/drivers/acpi/drivers/core/Makefile @@ -2,6 +2,8 @@ obj-y := bus.o device.o driver.o obj-y += lib.o +obj-$(CONFIG_ACPI_DM_SYSFS) += sysfs.o + ifeq ($(CONFIG_ACPI_DM_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/acpi/drivers/core/device.c b/drivers/acpi/drivers/core/device.c index d91116b..bd70682 100644 --- a/drivers/acpi/drivers/core/device.c +++ b/drivers/acpi/drivers/core/device.c @@ -11,6 +11,7 @@ */ #include "core.h" +#include "sysfs.h" static void acpi_dev_release(struct device * dev) @@ -21,14 +22,25 @@ static void acpi_dev_release(struct devi int acpi_device_register(struct acpi_dev * ad) { + int ret; + ad->dev.bus = &acpi_bus; ad->dev.release = acpi_dev_release; - return device_register(&ad->dev); + ret = device_register(&ad->dev); + + if (!ret) { + ret = acpi_sysfs_device_register(ad); + + if (ret) + device_unregister(&ad->dev); + } + return ret; } void acpi_device_unregister(struct acpi_dev * ad) { + acpi_sysfs_device_unregister(ad); device_unregister(&ad->dev); } diff --git a/drivers/acpi/drivers/core/sysfs.c b/drivers/acpi/drivers/core/sysfs.c new file mode 100644 index 0000000..ac3f08e --- /dev/null +++ b/drivers/acpi/drivers/core/sysfs.c @@ -0,0 +1,124 @@ +/** + * + * drivers/acpi/drivers/sysfs.c - Sysfs interface for ACPI device drivers. + * + * Copyright (C) 2006 Patrick Mochel + * + * This file is release under the GPLv2 + * + */ + +#include "core.h" + + +struct acpi_dev_attr { + struct device_attribute attr; + int (*test)(struct acpi_dev * ad); +}; + +#define define_acpi_attr(__name) \ + { .attr = __ATTR_RO(__name), .test = __name##_test, } + + + +/** + * Default attributes for ACPI objects and devices + */ + +static ssize_t uid_show(struct device * d, struct device_attribute * a, char * buffer) +{ + struct acpi_dev * ad = to_acpi_dev(d); + + return sprintf(buffer, "%s\n", acpi_dev_uid(ad)); +} + +static int uid_test(struct acpi_dev * ad) +{ + return (strlen(acpi_dev_uid(ad)) > 0); +} + + +static ssize_t hid_show(struct device * d, struct device_attribute * a, char * buffer) +{ + struct acpi_dev * ad = to_acpi_dev(d); + + return sprintf(buffer, "%s\n", acpi_dev_hid(ad)); +} + +static int hid_test(struct acpi_dev * ad) +{ + return (strlen(acpi_dev_hid(ad)) > 0); +} + + +static ssize_t cid_show(struct device * d, struct device_attribute * a, char * buffer) +{ + struct acpi_dev * ad = to_acpi_dev(d); + ssize_t remain = PAGE_SIZE; + ssize_t ret = 0; + char * s = buffer; + int i; + + if (ad->acpi_device->pnp.cid_list) { + struct acpi_compatible_id_list * c = ad->acpi_device->pnp.cid_list; + + for (i = 0; i < c->count; i++) { + ssize_t count = snprintf(s, remain, "%s ", c->id[i].value); + + if ((remain - count) > 0) { + s += count; + ret += count; + remain -= count; + } else + break; + } + + if (ret > 0 && ret < PAGE_SIZE) + buffer[ret - 1] = '\n'; + } + return ret; +} + +static int cid_test(struct acpi_dev * ad) +{ + return (ad->acpi_device->pnp.cid_list != NULL); +} + + + +static struct acpi_dev_attr acpi_dev_attrs[] = { + define_acpi_attr(uid), + define_acpi_attr(hid), + define_acpi_attr(cid), +}; + + +void acpi_sysfs_device_unregister(struct acpi_dev * ad) +{ + int num = ARRAY_SIZE(acpi_dev_attrs); + int i; + + for (i = 0; i < num; i++) { + if (acpi_dev_attrs[i].test(ad)) + device_remove_file(&ad->dev, &acpi_dev_attrs[i].attr); + } +} + +int acpi_sysfs_device_register(struct acpi_dev * ad) +{ + int num = ARRAY_SIZE(acpi_dev_attrs); + int i; + int ret = 0; + + for (i = 0; i < num; i++) { + if (acpi_dev_attrs[i].test(ad)) { + ret = device_create_file(&ad->dev, &acpi_dev_attrs[i].attr); + if (ret) { + acpi_sysfs_device_unregister(ad); + break; + } + } + } + return ret; +} + diff --git a/drivers/acpi/drivers/core/sysfs.h b/drivers/acpi/drivers/core/sysfs.h new file mode 100644 index 0000000..0333fe7 --- /dev/null +++ b/drivers/acpi/drivers/core/sysfs.h @@ -0,0 +1,28 @@ +/** + * + * drivers/acpi/drivers/core/sysfs.h + * + * sysfs interface for the ACPI driver model. + */ + + +#include + +#ifdef CONFIG_ACPI_DM_SYSFS +extern int acpi_sysfs_device_register(struct acpi_dev * ad); +extern void acpi_sysfs_device_unregister(struct acpi_dev * ad); +#else /* CONFIG_ACPI_DM_SYSFS */ + +static inline int acpi_sysfs_device_register(struct acpi_dev * ad) +{ + return 0; +} + + +static inline void acpi_sysfs_device_unregister(struct acpi_dev * ad) +{ + +} + +#endif /* CONFIG_ACPI_DM_SYSFS */ + --- 0.99.9.GIT