[RFC 1/2] add new hwmon-core interface v3

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



v3: now checkpatch clean (doh!)
Many of the errors were caused by my attempt to make all these
definitions readable. Now I think I have a good compromise between
readability and making checkpatch happy.


This adds a new hwmon-core interface to centralize sysfs handling
and enable cooperation with other in-kernel drivers.

Signed-off-by: Lucas Stach <dev@xxxxxxxxxx>
---
 drivers/hwmon/Makefile     |    1 +
 drivers/hwmon/hwmon-core.c |  459 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/hwmon-core.h |  322 +++++++++++++++++++++++++++++++
 3 files changed, 782 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/hwmon-core.c
 create mode 100644 include/linux/hwmon-core.h

diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3c9ccef..3d5b395 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_HWMON)		+= hwmon.o
+obj-$(CONFIG_HWMON)		+= hwmon-core.o
 obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
 
 # APCI drivers
diff --git a/drivers/hwmon/hwmon-core.c b/drivers/hwmon/hwmon-core.c
new file mode 100644
index 0000000..36798a6
--- /dev/null
+++ b/drivers/hwmon/hwmon-core.c
@@ -0,0 +1,459 @@
+/*
+ * hwmon-core.c
+ * Copyright (C) 2011 Lucas Stach
+ *
+ * hwmon-core interface implementation
+ *
+ * Provides functions to create/destroy a sysfs interface out of a
+ * hwmon_device_instance definition. The hwmon_device_instance interface could
+ * also be used to communicate with other drivers within the kernel.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/hwmon-core.h>
+#include <linux/hwmon-sysfs.h>
+
+/* building blocks */
+
+#define HWMON_NAME_SIZE 32
+
+struct hwmon_device_attribute {
+	struct sensor_device_attribute sensor_dev;
+	struct hwmon_device_instance *hw_dev_inst;
+	enum hwmon_attr attr_enum;
+	char name[HWMON_NAME_SIZE];
+	struct list_head node;
+};
+
+enum entry_type {
+	value,
+	text
+};
+
+enum entry_count {
+	single,
+	multi
+};
+
+struct caps_info {
+	char *format;
+	mode_t mode;
+	enum hwmon_attr attr;
+	enum entry_type type;
+	enum entry_count count;
+};
+
+/* caps_info structs are used to define how the sysfs interface looks like*/
+
+static struct caps_info generic_caps_info[] = {
+	[generic_name] =	{"name", S_IRUGO,
+				hwmon_attr_generic_name, text, single},
+	[generic_update_interval] =	{"update_interval", S_IRUGO|S_IWUGO,
+					hwmon_attr_generic_update_interval,
+					value, single}
+};
+
+static struct caps_info in_caps_info[] = {
+	[in_input] =	{"in%u_input", S_IRUGO,
+			hwmon_attr_in_input, value, multi},
+	[in_min] =	{"in%u_min", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_min, value, multi},
+	[in_max] =	{"in%u_max", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_max, value, multi},
+	[in_lcrit] =	{"in%u_lcrit", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_lcrit, value, multi},
+	[in_crit] =	{"in%u_crit", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_crit, value, multi},
+	[in_average] =	{"in%u_average", S_IRUGO,
+			hwmon_attr_in_average, value, multi},
+	[in_lowest] =	{"in%u_lowest", S_IRUGO,
+			hwmon_attr_in_lowest, value, multi},
+	[in_highest] =	{"in%u_highest", S_IRUGO,
+			hwmon_attr_in_highest, value, multi},
+	[in_reset_history] =	{"in%u_reset_history", S_IWUGO,
+				hwmon_attr_in_reset_history, value, multi},
+	[in_reset_history_glob] =	{"in_reset_history", S_IWUGO,
+					hwmon_attr_in_reset_history_glob,
+					value, single},
+	[in_label] =	{"in%u_label", S_IRUGO,
+			hwmon_attr_in_label, text, multi},
+	[in_alarm] =	{"in%u_alarm", S_IRUGO,
+			hwmon_attr_in_alarm, value, multi},
+	[in_min_alarm] =	{"in%u_min_alarm", S_IRUGO,
+				hwmon_attr_in_min_alarm, value, multi},
+	[in_max_alarm] =	{"in%u_max_alarm", S_IRUGO,
+				hwmon_attr_in_max_alarm, value, multi},
+	[in_lcrit_alarm] =	{"in%u_lcrit_alarm", S_IRUGO,
+				hwmon_attr_in_lcrit_alarm, value, multi},
+	[in_crit_alarm] =	{"in%u_crit_alarm", S_IRUGO,
+				hwmon_attr_in_crit_alarm, value, multi},
+	[in_vid] =	{"cpu%u_vid", S_IRUGO,
+			hwmon_attr_in_vid, value, multi},
+	[in_vrm] =	{"vrm", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_vrm, value, single},
+	[in_beep] =	{"in%u_beep", S_IRUGO|S_IWUGO,
+			hwmon_attr_in_beep, value, multi}
+};
+
+static struct caps_info fan_caps_info[] = {
+	[fan_input] =	{"fan%u_input", S_IRUGO,
+			hwmon_attr_fan_input, value, multi},
+	[fan_min] =	{"fan%u_min", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_min, value, multi},
+	[fan_max] =	{"fan%u_max", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_max, value, multi},
+	[fan_div] =	{"fan%u_div", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_div, value, multi},
+	[fan_pulses] =	{"fan%u_pulses", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_pulses, value, multi},
+	[fan_target] =	{"fan%u_target", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_target, value, multi},
+	[fan_label] =	{"fan%u_label", S_IRUGO,
+			hwmon_attr_fan_label, text, multi},
+	[fan_alarm] =	{"fan%u_alarm", S_IRUGO,
+			hwmon_attr_fan_alarm, value, multi},
+	[fan_beep] =	{"fan%u_beep", S_IRUGO|S_IWUGO,
+			hwmon_attr_fan_beep, value, multi},
+	[fan_fault] =	{"fan%u_fault", S_IRUGO,
+			hwmon_attr_fan_fault, value, multi}
+};
+
+static struct caps_info pwm_caps_info[] = {
+	[pwm] =		{"pwm%u", S_IRUGO|S_IWUGO,
+			hwmon_attr_pwm, value, multi},
+	[pwm_enable] =  {"pwm%u_enable", S_IRUGO|S_IWUGO,
+			hwmon_attr_pwm_enable, value, multi},
+	[pwm_mode] =	{"pwm%u_mode", S_IRUGO|S_IWUGO,
+			hwmon_attr_pwm_mode, value, multi},
+	[pwm_freq] =	{"pwm%u_freq", S_IRUGO|S_IWUGO,
+			hwmon_attr_pwm_freq, value, multi},
+	[pwm_auto_channels_temp] =	{"pwm%u_auto_channels_temp",
+					S_IRUGO|S_IWUGO, hwmon_attr_pwm_freq,
+					value, multi}
+};
+
+static struct caps_info temp_caps_info[] = {
+	[temp_type] =		{"temp%u_type,", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_type, value, multi},
+	[temp_input] =		{"temp%u_input", S_IRUGO,
+				hwmon_attr_temp_input, value, multi},
+	[temp_min] =		{"temp%u_min", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_min, value, multi},
+	[temp_max] =		{"temp%u_max", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_max, value, multi},
+	[temp_max_hyst] =	{"temp%u_max_hyst", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_max_hyst, value, multi},
+	[temp_lcrit] =		{"temp%u_lcrit", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_lcrit, value, multi},
+	[temp_crit] =		{"temp%u_crit", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_crit, value, multi},
+	[temp_crit_hyst] =	{"temp%u_crit_hyst", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_crit_hyst, value, multi},
+	[temp_emergency] =	{"temp%u_emergency", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_emergency, value, multi},
+	[temp_emergency_hyst] =	{"temp%u_emergency_hyst", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_emergency_hyst, value, multi},
+	[temp_offset] =		{"temp%u_offset", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_offset, value, multi},
+	[temp_label] =		{"temp%u_label", S_IRUGO,
+				hwmon_attr_temp_label, text, multi},
+	[temp_lowest] =		{"temp%u_lowest", S_IRUGO,
+				hwmon_attr_temp_lowest, value, multi},
+	[temp_highest] =	{"temp%u_highest", S_IRUGO,
+				hwmon_attr_temp_highest, value, multi},
+	[temp_reset_history] =	{"temp%u_reset_history", S_IWUGO,
+				hwmon_attr_temp_reset_history, value, multi},
+	[temp_reset_history_glob] =	{"temp_reset_history", S_IWUGO,
+					hwmon_attr_temp_reset_history_glob,
+					value, single},
+	[temp_alarm] =		{"temp%u_alarm", S_IRUGO,
+				hwmon_attr_temp_alarm, value, multi},
+	[temp_min_alarm] =	{"temp%u_min_alarm", S_IRUGO,
+				hwmon_attr_temp_min_alarm, value, multi},
+	[temp_max_alarm] =	{"temp%u_max_alarm", S_IRUGO,
+				hwmon_attr_temp_max_alarm, value, multi},
+	[temp_lcrit_alarm] =	{"temp%u_lcrit_alarm", S_IRUGO,
+				hwmon_attr_temp_lcrit_alarm, value, multi},
+	[temp_crit_alarm] =	{"temp%u_crit_alarm", S_IRUGO,
+				hwmon_attr_temp_crit_alarm, value, multi},
+	[temp_emergency_alarm] =	{"temp%u_emergency_alarm", S_IRUGO,
+					hwmon_attr_temp_emergency_alarm,
+					value, multi},
+	[temp_beep] =		{"temp%u_beep", S_IRUGO|S_IWUGO,
+				hwmon_attr_temp_beep, value, multi},
+	[temp_fault] =		{"temp%u_fault", S_IRUGO,
+				hwmon_attr_temp_fault, value, multi}
+};
+
+static struct caps_info curr_caps_info[] = {
+	[curr_input] =		{"curr%u_input", S_IRUGO,
+				hwmon_attr_curr_input, value, multi},
+	[curr_min] =		{"curr%u_min", S_IRUGO|S_IWUGO,
+				hwmon_attr_curr_min, value, multi},
+	[curr_max] =		{"curr%u_max", S_IRUGO|S_IWUGO,
+				hwmon_attr_curr_max, value, multi},
+	[curr_lcrit] =		{"curr%u_lcrit", S_IRUGO|S_IWUGO,
+				hwmon_attr_curr_lcrit, value, multi},
+	[curr_crit] =		{"curr%u_crit", S_IRUGO|S_IWUGO,
+				hwmon_attr_curr_crit, value, multi},
+	[curr_average] =	{"curr%u_average", S_IRUGO,
+				hwmon_attr_curr_average, value, multi},
+	[curr_lowest] =		{"curr%u_lowest", S_IRUGO,
+				hwmon_attr_curr_lowest, value, multi},
+	[curr_highest] =	{"curr%u_highest", S_IRUGO,
+				hwmon_attr_curr_highest, value, multi},
+	[curr_reset_history] =	{"curr%u_reset_history", S_IWUGO,
+				hwmon_attr_curr_reset_history, value, multi},
+	[curr_reset_history_glob] =	{"curr_reset_history", S_IWUGO,
+					hwmon_attr_curr_reset_history_glob,
+					value, single},
+	[curr_alarm] =		{"curr%u_alarm", S_IRUGO,
+				hwmon_attr_curr_alarm, value, multi},
+	[curr_min_alarm] =	{"curr%u_min_alarm", S_IRUGO,
+				hwmon_attr_curr_min_alarm, value, multi},
+	[curr_max_alarm] =	{"curr%u_max_alarm", S_IRUGO,
+				hwmon_attr_curr_max_alarm, value, multi},
+	[curr_lcrit_alarm] =	{"curr%u_lcrit_alarm", S_IRUGO,
+				hwmon_attr_curr_lcrit_alarm, value, multi},
+	[curr_crit_alarm] =	{"curr%u_crit_alarm", S_IRUGO,
+				hwmon_attr_curr_crit_alarm, value, multi},
+	[curr_beep] =		{"curr%u_beep", S_IRUGO|S_IWUGO,
+				hwmon_attr_curr_beep, value, multi}
+};
+
+static struct caps_info power_caps_info[] = {
+	[power_input] =		{"power%u_input", S_IRUGO,
+				hwmon_attr_power_input, value, multi},
+	[power_input_lowest] =	{"power%u_input_lowest", S_IRUGO,
+				hwmon_attr_power_input_lowest, value, multi},
+	[power_input_highest] =	{"power%u_input_highest", S_IRUGO,
+				hwmon_attr_power_input_highest, value, multi},
+	[power_reset_history] =	{"power%u_reset_history", S_IWUGO,
+				hwmon_attr_power_reset_history, value, multi},
+	[power_reset_history_glob] =	{"power_reset_history", S_IWUGO,
+					hwmon_attr_power_reset_history_glob,
+					value, multi},
+	[power_accuracy] =	{"power%u_accuracy", S_IRUGO,
+				hwmon_attr_power_accuracy, value, multi},
+	[power_average]	=	{"power%u_average", S_IRUGO,
+				hwmon_attr_power_average, value, multi},
+	[power_average_interval] = {"power%u_average_interval", S_IRUGO|S_IWUGO,
+				   hwmon_attr_power_average_interval,
+				   value, multi},
+	[power_average_interval_min] = {"power%u_average_interval_min", S_IRUGO,
+				       hwmon_attr_power_average_min,
+				       value, multi},
+	[power_average_interval_max] = {"power%u_average_interval_max", S_IRUGO,
+				       hwmon_attr_power_average_max,
+				       value, multi},
+	[power_average_min] =	{"power%u_average_min", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_average_min, value, multi},
+	[power_average_max] =	{"power%u_average_max", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_average_max, value, multi},
+	[power_average_lowest] =	{"power%u_average_lowest", S_IRUGO,
+					hwmon_attr_power_average_lowest,
+					value, multi},
+	[power_average_highest] =	{"power%u_average_highest", S_IRUGO,
+					hwmon_attr_power_average_highest,
+					value, multi},
+	[power_cap] =		{"power%u_cap", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_cap, value, multi},
+	[power_cap_hyst] =	{"power%u_cap_hyst", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_cap_hyst, value, multi},
+	[power_cap_min] =	{"power%u_cap_min", S_IRUGO,
+				hwmon_attr_power_cap_min, value, multi},
+	[power_cap_max] =	{"power%u_cap_max", S_IRUGO,
+				hwmon_attr_power_cap_max, value, multi},
+	[power_max] =		{"power%u_max", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_max, value, multi},
+	[power_crit] =		{"power%u_crit", S_IRUGO|S_IWUGO,
+				hwmon_attr_power_crit, value, multi},
+	[power_alarm] =		{"power%u_alarm", S_IRUGO,
+				hwmon_attr_power_alarm, value, multi},
+	[power_cap_alarm] =	{"power%u_cap_alarm", S_IRUGO,
+				hwmon_attr_power_cap_alarm, value, multi},
+	[power_max_alarm] =	{"power%u_max_alarm", S_IRUGO,
+				hwmon_attr_power_max_alarm, value, multi},
+	[power_crit_alarm] =	{"power%u_crit_alarm", S_IRUGO,
+				hwmon_attr_power_crit_alarm, value, multi}
+};
+
+static struct caps_info energy_caps_info[] = {
+	[energy_input] =	{"energy%u_input", S_IRUGO,
+				hwmon_attr_energy_input, value, multi}
+};
+
+static struct caps_info humidity_caps_info[] = {
+	[humidity_input] =	{"humidity%u_input", S_IRUGO,
+				hwmon_attr_humidity_input, value, multi}
+};
+
+static struct caps_info intrusion_caps_info[] = {
+	[intrusion_alarm] =	{"intrusion%u_alarm", S_IRUGO|S_IWUGO,
+				hwmon_attr_intrusion_alarm, value, multi},
+	[intrusion_beep] =	{"intrusion%u_beep", S_IRUGO|S_IWUGO,
+				hwmon_attr_intrusion_beep, value, multi}
+};
+
+static struct caps_info *caps_lookup[] = {
+	generic_caps_info,
+	in_caps_info,
+	fan_caps_info,
+	pwm_caps_info,
+	temp_caps_info,
+	curr_caps_info,
+	power_caps_info,
+	energy_caps_info,
+	humidity_caps_info,
+	intrusion_caps_info
+};
+
+/* basic building block functions */
+
+#define to_hwmon_device_attr(_sensor_attr) \
+	container_of(_sensor_attr, struct hwmon_device_attribute, sensor_dev)
+
+static ssize_t get_text(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct hwmon_device_attribute *hw_attr = to_hwmon_device_attr(attr);
+	struct hwmon_device_instance *hw_dev = hw_attr->hw_dev_inst;
+	return hw_dev->get_text_attr(hw_dev->inst_data,
+				     hw_attr->attr_enum, attr->index, buf);
+}
+
+static ssize_t get_num(struct device *dev,
+		       struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct hwmon_device_attribute *hw_attr = to_hwmon_device_attr(attr);
+	struct hwmon_device_instance *hw_dev = hw_attr->hw_dev_inst;
+	int value, ret;
+	ret = hw_dev->get_numeric_attr(hw_dev->inst_data,
+				       hw_attr->attr_enum, attr->index, &value);
+	if (ret)
+		return ret;
+	ret = snprintf(buf, PAGE_SIZE, "%u\n", value);
+	return ret;
+}
+
+static ssize_t set_num(struct device *dev, struct device_attribute *devattr,
+		       const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct hwmon_device_attribute *hw_attr = to_hwmon_device_attr(attr);
+	struct hwmon_device_instance *hw_dev = hw_attr->hw_dev_inst;
+	long value;
+	if (strict_strtol(buf, 10, &value))
+		return -EINVAL;
+	hw_dev->set_numeric_attr(hw_dev->inst_data,
+				 hw_attr->attr_enum, attr->index, value);
+	return count;
+}
+
+/* functions to build/destroy sysfs */
+
+static int new_sysfs_entry(const char *name, mode_t mode, enum hwmon_attr attr,
+		enum entry_type type, int index, struct list_head *list,
+		struct device *dev)
+{
+	struct hwmon_device_attribute *hw_dev_attr;
+	int ret = 0;
+
+	hw_dev_attr = kzalloc(sizeof(struct hwmon_device_attribute),
+			      GFP_KERNEL);
+	if (!hw_dev_attr)
+		return -ENOMEM;
+
+	strlcpy(hw_dev_attr->name, name, HWMON_NAME_SIZE);
+
+	hw_dev_attr->sensor_dev.dev_attr.attr.mode = mode;
+	if (mode && S_IRUGO) {
+		if (type == value)
+			hw_dev_attr->sensor_dev.dev_attr.show = &get_num;
+		else
+			hw_dev_attr->sensor_dev.dev_attr.show = &get_text;
+	}
+	if (mode && S_IWUGO)
+		hw_dev_attr->sensor_dev.dev_attr.store = &set_num;
+
+	hw_dev_attr->sensor_dev.dev_attr.attr.name = hw_dev_attr->name;
+	hw_dev_attr->sensor_dev.index = index;
+	hw_dev_attr->hw_dev_inst = dev_get_drvdata(dev);
+	hw_dev_attr->attr_enum = attr;
+	sysfs_attr_init(&hw_dev_attr->sensor_dev.dev_attr.attr);
+
+	ret = device_create_file(dev->parent,
+				 &hw_dev_attr->sensor_dev.dev_attr);
+	if (ret) {
+		kfree(hw_dev_attr);
+		return ret;
+	}
+
+	list_add(&hw_dev_attr->node, list);
+
+	return 0;
+}
+
+int hwmon_create_sysfs(struct device *dev)
+{
+	struct hwmon_device_instance *hw_dev = dev_get_drvdata(dev);
+	struct hwmon_device_caps *caps = hw_dev->caps;
+	char attr_name[HWMON_NAME_SIZE];
+	int i, j, count;
+	unsigned long bit;
+
+	INIT_LIST_HEAD(&hw_dev->sysfs_node);
+
+	for (i = 0; i < hwmon_feature_size; i++) {
+		if (!caps->num_channels[i])
+			continue;
+
+		for_each_set_bit(bit, (long *)&caps->subfeature_caps[i], 32) {
+			struct caps_info info = caps_lookup[i][bit];
+			count = (info.count == single) ?
+					1 : caps->num_channels[i];
+			for (j = 1; j <= count; j++) {
+				snprintf(attr_name, HWMON_NAME_SIZE,
+					 info.format, j);
+				if (new_sysfs_entry(attr_name, info.mode,
+						    info.attr, info.type, j,
+						    &hw_dev->sysfs_node, dev))
+					goto fail;
+			}
+		}
+	}
+
+	return 0;
+
+fail:
+	hwmon_destroy_sysfs(dev);
+	return -EAGAIN;
+}
+EXPORT_SYMBOL_GPL(hwmon_create_sysfs);
+
+void hwmon_destroy_sysfs(struct device *dev)
+{
+	struct hwmon_device_instance *hw_dev = dev_get_drvdata(dev);
+	struct hwmon_device_attribute *hw_dev_attr, *tmp;
+
+	list_for_each_entry_safe(hw_dev_attr, tmp, &hw_dev->sysfs_node, node) {
+		device_remove_file(dev, &hw_dev_attr->sensor_dev.dev_attr);
+		list_del(&hw_dev_attr->node);
+		kfree(hw_dev_attr);
+	}
+}
+EXPORT_SYMBOL_GPL(hwmon_destroy_sysfs);
+
+MODULE_AUTHOR("Lucas Stach <dev@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Hardware monitoring core API");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/hwmon-core.h b/include/linux/hwmon-core.h
new file mode 100644
index 0000000..36758fb
--- /dev/null
+++ b/include/linux/hwmon-core.h
@@ -0,0 +1,322 @@
+/**
+ * hwmon-core.h
+ * Copyright (C) 2011 Lucas Stach
+ *
+ * hwmon-core interface definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef HWMON_CORE_H_
+#define HWMON_CORE_H_
+
+int hwmon_create_sysfs(struct device *dev);
+
+void hwmon_destroy_sysfs(struct device *dev);
+
+/*
+ * enum hwmon_attr: used as central index to get/set attribute functions
+ */
+enum hwmon_attr {
+	hwmon_attr_generic_name,
+	hwmon_attr_generic_update_interval,
+
+	hwmon_attr_in_input,
+	hwmon_attr_in_min,
+	hwmon_attr_in_max,
+	hwmon_attr_in_lcrit,
+	hwmon_attr_in_crit,
+	hwmon_attr_in_average,
+	hwmon_attr_in_lowest,
+	hwmon_attr_in_highest,
+	hwmon_attr_in_reset_history,
+	hwmon_attr_in_reset_history_glob,
+	hwmon_attr_in_label,
+	hwmon_attr_in_alarm,
+	hwmon_attr_in_min_alarm,
+	hwmon_attr_in_max_alarm,
+	hwmon_attr_in_lcrit_alarm,
+	hwmon_attr_in_crit_alarm,
+	hwmon_attr_in_vid,
+	hwmon_attr_in_vrm,
+	hwmon_attr_in_beep,
+
+	hwmon_attr_fan_input,
+	hwmon_attr_fan_min,
+	hwmon_attr_fan_max,
+	hwmon_attr_fan_div,
+	hwmon_attr_fan_pulses,
+	hwmon_attr_fan_target,
+	hwmon_attr_fan_label,
+	hwmon_attr_fan_alarm,
+	hwmon_attr_fan_beep,
+	hwmon_attr_fan_fault,
+
+	hwmon_attr_pwm,
+	hwmon_attr_pwm_enable,
+	hwmon_attr_pwm_mode,
+	hwmon_attr_pwm_freq,
+	hwmon_attr_pwm_auto_channels_temp,
+
+	hwmon_attr_temp_type,
+	hwmon_attr_temp_input,
+	hwmon_attr_temp_min,
+	hwmon_attr_temp_max,
+	hwmon_attr_temp_max_hyst,
+	hwmon_attr_temp_lcrit,
+	hwmon_attr_temp_crit,
+	hwmon_attr_temp_crit_hyst,
+	hwmon_attr_temp_emergency,
+	hwmon_attr_temp_emergency_hyst,
+	hwmon_attr_temp_offset,
+	hwmon_attr_temp_label,
+	hwmon_attr_temp_lowest,
+	hwmon_attr_temp_highest,
+	hwmon_attr_temp_reset_history,
+	hwmon_attr_temp_reset_history_glob,
+	hwmon_attr_temp_alarm,
+	hwmon_attr_temp_min_alarm,
+	hwmon_attr_temp_max_alarm,
+	hwmon_attr_temp_lcrit_alarm,
+	hwmon_attr_temp_crit_alarm,
+	hwmon_attr_temp_emergency_alarm,
+	hwmon_attr_temp_beep,
+	hwmon_attr_temp_fault,
+
+	hwmon_attr_curr_input,
+	hwmon_attr_curr_min,
+	hwmon_attr_curr_max,
+	hwmon_attr_curr_lcrit,
+	hwmon_attr_curr_crit,
+	hwmon_attr_curr_average,
+	hwmon_attr_curr_lowest,
+	hwmon_attr_curr_highest,
+	hwmon_attr_curr_reset_history,
+	hwmon_attr_curr_reset_history_glob,
+	hwmon_attr_curr_alarm,
+	hwmon_attr_curr_min_alarm,
+	hwmon_attr_curr_max_alarm,
+	hwmon_attr_curr_lcrit_alarm,
+	hwmon_attr_curr_crit_alarm,
+	hwmon_attr_curr_beep,
+
+	hwmon_attr_power_input,
+	hwmon_attr_power_input_lowest,
+	hwmon_attr_power_input_highest,
+	hwmon_attr_power_reset_history,
+	hwmon_attr_power_reset_history_glob,
+	hwmon_attr_power_accuracy,
+	hwmon_attr_power_average,
+	hwmon_attr_power_average_interval,
+	hwmon_attr_power_average_interval_min,
+	hwmon_attr_power_average_interval_max,
+	hwmon_attr_power_average_min,
+	hwmon_attr_power_average_max,
+	hwmon_attr_power_average_lowest,
+	hwmon_attr_power_average_highest,
+	hwmon_attr_power_cap,
+	hwmon_attr_power_cap_hyst,
+	hwmon_attr_power_cap_min,
+	hwmon_attr_power_cap_max,
+	hwmon_attr_power_max,
+	hwmon_attr_power_crit,
+	hwmon_attr_power_alarm,
+	hwmon_attr_power_cap_alarm,
+	hwmon_attr_power_max_alarm,
+	hwmon_attr_power_crit_alarm,
+
+	hwmon_attr_energy_input,
+
+	hwmon_attr_humidity_input,
+
+	hwmon_attr_intrusion_alarm,
+	hwmon_attr_intrusion_beep
+};
+
+/*
+ * enum hwmon_feature: used as a lookup into the channel and subfeature array
+ */
+enum hwmon_feature {
+	hwmon_feature_generic,
+	hwmon_feature_in,
+	hwmon_feature_fan,
+	hwmon_feature_pwm,
+	hwmon_feature_temp,
+	hwmon_feature_curr,
+	hwmon_feature_power,
+	hwmon_feature_energy,
+	hwmon_feature_humidity,
+	hwmon_feature_intrusion,
+
+	hwmon_feature_size /* dummy entry */
+};
+
+/*
+ * enums to describe the position of the subfeature caps in their
+ * respective bitfields
+ */
+enum generic_caps {
+	generic_name,
+	generic_update_interval
+};
+
+enum in_caps {
+	in_input,
+	in_min,
+	in_max,
+	in_lcrit,
+	in_crit,
+	in_average,
+	in_lowest,
+	in_highest,
+	in_reset_history,
+	in_reset_history_glob,
+	in_label,
+	in_alarm,
+	in_min_alarm,
+	in_max_alarm,
+	in_lcrit_alarm,
+	in_crit_alarm,
+	in_vid,
+	in_vrm,
+	in_beep
+};
+
+enum fan_caps {
+	fan_input,
+	fan_min,
+	fan_max,
+	fan_div,
+	fan_pulses,
+	fan_target,
+	fan_label,
+	fan_alarm,
+	fan_beep,
+	fan_fault
+};
+
+enum pwm_caps {
+	pwm,
+	pwm_enable,
+	pwm_mode,
+	pwm_freq,
+	pwm_auto_channels_temp
+};
+
+enum temp_caps {
+	temp_type,
+	temp_input,
+	temp_min,
+	temp_max,
+	temp_max_hyst,
+	temp_lcrit,
+	temp_crit,
+	temp_crit_hyst,
+	temp_emergency,
+	temp_emergency_hyst,
+	temp_offset,
+	temp_label,
+	temp_lowest,
+	temp_highest,
+	temp_reset_history,
+	temp_reset_history_glob,
+	temp_alarm,
+	temp_min_alarm,
+	temp_max_alarm,
+	temp_lcrit_alarm,
+	temp_crit_alarm,
+	temp_emergency_alarm,
+	temp_beep,
+	temp_fault
+};
+
+enum curr_caps {
+	curr_input,
+	curr_min,
+	curr_max,
+	curr_lcrit,
+	curr_crit,
+	curr_average,
+	curr_lowest,
+	curr_highest,
+	curr_reset_history,
+	curr_reset_history_glob,
+	curr_alarm,
+	curr_min_alarm,
+	curr_max_alarm,
+	curr_lcrit_alarm,
+	curr_crit_alarm,
+	curr_beep
+};
+
+enum power_caps {
+	power_input,
+	power_input_lowest,
+	power_input_highest,
+	power_reset_history,
+	power_reset_history_glob,
+	power_accuracy,
+	power_average,
+	power_average_interval,
+	power_average_interval_min,
+	power_average_interval_max,
+	power_average_min,
+	power_average_max,
+	power_average_lowest,
+	power_average_highest,
+	power_cap,
+	power_cap_hyst,
+	power_cap_min,
+	power_cap_max,
+	power_max,
+	power_crit,
+	power_alarm,
+	power_cap_alarm,
+	power_max_alarm,
+	power_crit_alarm
+};
+
+enum energy_caps {
+	energy_input
+};
+
+enum humidity_caps {
+	humidity_input
+};
+
+enum intrusion_caps {
+	intrusion_alarm,
+	intrusion_beep
+};
+
+/* the core interface */
+
+struct hwmon_device_caps {
+	/* number of channels
+	 * (feature to index mapping through enum hwmon_feature)
+	 * a channel count of 0 denotes an unsupported feature
+	 */
+	u8 num_channels[hwmon_feature_size];
+
+	/* array of bitfields to advertise supported subfeatures */
+	u32 subfeature_caps[hwmon_feature_size];
+};
+
+struct hwmon_device_instance {
+	struct hwmon_device_caps *caps;
+	int (*get_numeric_attr) (void *inst_data, enum hwmon_attr attr,
+			unsigned int index, int *value);
+	int (*get_text_attr) (void *inst_data, enum hwmon_attr attr,
+			unsigned int index, char *buf);
+	int (*set_numeric_attr) (void *inst_data, enum hwmon_attr attr,
+			unsigned int index, int value);
+	struct list_head sysfs_node;
+	void *inst_data;
+};
+
+/* helper function to assist filling the subfeature bitfields */
+#define HWMON_CAP(_cap_enum) (u32)BIT(_cap_enum)
+
+#endif /* HWMON_CORE_H_ */
-- 
1.7.6



_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux