static int atk_add_sensor()

in asus_atk0110.c [820:936]


static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
{
	struct device *dev = &data->acpi_dev->dev;
	union acpi_object *flags;
	union acpi_object *name;
	union acpi_object *limit1;
	union acpi_object *limit2;
	union acpi_object *enable;
	struct atk_sensor_data *sensor;
	char const *base_name;
	char const *limit1_name;
	char const *limit2_name;
	u64 type;
	int err;
	int *num;
	int start;

	if (obj->type != ACPI_TYPE_PACKAGE) {
		/* wft is this? */
		dev_warn(dev, "Unknown type for ACPI object: (%d)\n",
				obj->type);
		return -EINVAL;
	}

	err = validate_hwmon_pack(data, obj);
	if (err)
		return err;

	/* Ok, we have a valid hwmon package */
	type = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS)->integer.value
	       & ATK_TYPE_MASK;

	switch (type) {
	case HWMON_TYPE_VOLT:
		base_name = "in";
		limit1_name = "min";
		limit2_name = "max";
		num = &data->voltage_count;
		start = 0;
		break;
	case HWMON_TYPE_TEMP:
		base_name = "temp";
		limit1_name = "max";
		limit2_name = "crit";
		num = &data->temperature_count;
		start = 1;
		break;
	case HWMON_TYPE_FAN:
		base_name = "fan";
		limit1_name = "min";
		limit2_name = "max";
		num = &data->fan_count;
		start = 1;
		break;
	default:
		dev_warn(dev, "Unknown sensor type: %#llx\n", type);
		return -EINVAL;
	}

	enable = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE);
	if (!enable->integer.value)
		/* sensor is disabled */
		return 0;

	flags = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS);
	name = atk_get_pack_member(data, obj, HWMON_PACK_NAME);
	limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1);
	limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2);

	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
	if (!sensor)
		return -ENOMEM;

	sensor->acpi_name = devm_kstrdup(dev, name->string.pointer, GFP_KERNEL);
	if (!sensor->acpi_name)
		return -ENOMEM;

	INIT_LIST_HEAD(&sensor->list);
	sensor->type = type;
	sensor->data = data;
	sensor->id = flags->integer.value;
	sensor->limit1 = limit1->integer.value;
	if (data->old_interface)
		sensor->limit2 = limit2->integer.value;
	else
		/* The upper limit is expressed as delta from lower limit */
		sensor->limit2 = sensor->limit1 + limit2->integer.value;

	snprintf(sensor->input_attr_name, ATTR_NAME_SIZE,
			"%s%d_input", base_name, start + *num);
	atk_init_attribute(&sensor->input_attr,
			sensor->input_attr_name,
			atk_input_show);

	snprintf(sensor->label_attr_name, ATTR_NAME_SIZE,
			"%s%d_label", base_name, start + *num);
	atk_init_attribute(&sensor->label_attr,
			sensor->label_attr_name,
			atk_label_show);

	snprintf(sensor->limit1_attr_name, ATTR_NAME_SIZE,
			"%s%d_%s", base_name, start + *num, limit1_name);
	atk_init_attribute(&sensor->limit1_attr,
			sensor->limit1_attr_name,
			atk_limit1_show);

	snprintf(sensor->limit2_attr_name, ATTR_NAME_SIZE,
			"%s%d_%s", base_name, start + *num, limit2_name);
	atk_init_attribute(&sensor->limit2_attr,
			sensor->limit2_attr_name,
			atk_limit2_show);

	list_add(&sensor->list, &data->sensor_list);
	(*num)++;

	return 1;
}