在 2023/6/21 23:33, Guenter Roeck 写道:
On Wed, Jun 21, 2023 at 11:59:36AM +0800, JuenKit Yip wrote:update_interval, temperature/humidity max/min and hyst were moved to new hwmon interface, and only heater and repeatability were reserved as non-stardard sysfs interface. Signed-off-by: JuenKit Yip <JuenKit_Yip@xxxxxxxxxxx> --- drivers/hwmon/sht3x.c | 351 ++++++++++++++++++++++++++++-------------- 1 file changed, 239 insertions(+), 112 deletions(-) diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c index bf1863061..31013b5b6 100644 --- a/drivers/hwmon/sht3x.c +++ b/drivers/hwmon/sht3x.c @@ -147,6 +147,37 @@ static const u16 mode_to_update_interval[] = { 100, };+static const struct hwmon_channel_info * const sht3x_channel_info[] = {+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN | + HWMON_T_MIN_HYST | HWMON_T_MAX | + HWMON_T_MAX_HYST | HWMON_T_ALARM), + HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN | + HWMON_H_MIN_HYST | HWMON_H_MAX | + HWMON_H_MAX_HYST | HWMON_H_ALARM), + NULL, +}; + +static const struct i2c_device_id sht3x_ids[]; + +static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel); +static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val); +static int sht3x_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val); +No forward declarations, please.+static const struct hwmon_ops sht3x_ops = { + .is_visible = sht3x_is_visible, + .read = sht3x_read, + .write = sht3x_write, +}; + +static const struct hwmon_chip_info sht3x_chip_info = { + .ops = &sht3x_ops, + .info = sht3x_channel_info, +}; + struct sht3x_data { struct i2c_client *client; struct mutex i2c_lock; /* lock for sending i2c commands */ @@ -277,26 +308,24 @@ static struct sht3x_data *sht3x_update_client(struct device *dev) }/* sysfs attributes */Those are no longer sysfs attributes.-static ssize_t temp1_input_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int temp1_input_show(struct device *dev)Drop _show from functions which no longer show anything.{ struct sht3x_data *data = sht3x_update_client(dev);if (IS_ERR(data))return PTR_ERR(data);- return sprintf(buf, "%d\n", data->temperature);+ return data->temperature; }-static ssize_t humidity1_input_show(struct device *dev,- struct device_attribute *attr, char *buf) +static int humidity1_input_show(struct device *dev) { struct sht3x_data *data = sht3x_update_client(dev);if (IS_ERR(data))return PTR_ERR(data);- return sprintf(buf, "%u\n", data->humidity);+ return data->humidity; }/*@@ -332,33 +361,24 @@ static int limits_update(struct sht3x_data *data) return ret; }-static ssize_t temp1_limit_show(struct device *dev,- struct device_attribute *attr, - char *buf) +static int temp1_limit_show(struct device *dev, int index) { struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - int temperature_limit = data->temperature_limits[index];- return sysfs_emit(buf, "%d\n", temperature_limit);+ return data->temperature_limits[index]; }-static ssize_t humidity1_limit_show(struct device *dev,- struct device_attribute *attr, - char *buf) +static ssize_t humidity1_limit_show(struct device *dev, int index)Return value is int.{ struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - u32 humidity_limit = data->humidity_limits[index];- return sysfs_emit(buf, "%u\n", humidity_limit);+ return data->humidity_limits[index]; }/** limit_store must only be called with data_lock held */ static size_t limit_store(struct device *dev,Drop _store from functions which are no longer sysfs store functions. Also, again, return values are int. Note that "size_t" is wrong in the current code; it should have been ssize_t since it can return a negative value.
I will review them again. Thanks
- size_t count, u8 index, int temperature, u32 humidity) @@ -400,50 +420,42 @@ static size_t limit_store(struct device *dev,data->temperature_limits[index] = temperature;data->humidity_limits[index] = humidity; - return count; + return 0; }-static ssize_t temp1_limit_store(struct device *dev,- struct device_attribute *attr, - const char *buf, - size_t count) +static int temp1_limit_store(struct device *dev, int index, const char *val) { int temperature; int ret; struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index;- ret = kstrtoint(buf, 0, &temperature);+ ret = kstrtoint(val, 0, &temperature); if (ret) return ret;temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE,SHT3X_MAX_TEMPERATURE); mutex_lock(&data->data_lock); - ret = limit_store(dev, count, index, temperature, + ret = limit_store(dev, index, temperature, data->humidity_limits[index]); mutex_unlock(&data->data_lock);- return ret;+ return 0;Ignore errors from limit_store() ? why ?}-static ssize_t humidity1_limit_store(struct device *dev,- struct device_attribute *attr, - const char *buf, - size_t count) +static ssize_t humidity1_limit_store(struct device *dev, int index, const char *val) { u32 humidity; int ret; struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index;- ret = kstrtou32(buf, 0, &humidity);+ ret = kstrtou32(val, 0, &humidity); if (ret) return ret;humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);mutex_lock(&data->data_lock); - ret = limit_store(dev, count, index, data->temperature_limits[index], + ret = limit_store(dev, index, data->temperature_limits[index], humidity); mutex_unlock(&data->data_lock);@@ -474,7 +486,6 @@ static void sht3x_select_command(struct sht3x_data *data)}static int status_register_read(struct device *dev,- struct device_attribute *attr, char *buffer, int length) { int ret; @@ -487,34 +498,30 @@ static int status_register_read(struct device *dev, return ret; }-static ssize_t temp1_alarm_show(struct device *dev,- struct device_attribute *attr, - char *buf) +static int temp1_alarm_show(struct device *dev) { char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret;- ret = status_register_read(dev, attr, buffer,+ ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret;- return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));+ return !!(buffer[0] & 0x04); }-static ssize_t humidity1_alarm_show(struct device *dev,- struct device_attribute *attr, - char *buf) +static int humidity1_alarm_show(struct device *dev) { char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret;- ret = status_register_read(dev, attr, buffer,+ ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret;- return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));+ return !!(buffer[0] & 0x08); }static ssize_t heater_enable_show(struct device *dev,@@ -524,7 +531,7 @@ static ssize_t heater_enable_show(struct device *dev, char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret;- ret = status_register_read(dev, attr, buffer,+ ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret; @@ -560,20 +567,14 @@ static ssize_t heater_enable_store(struct device *dev, return ret; }-static ssize_t update_interval_show(struct device *dev,- struct device_attribute *attr, - char *buf) +static int update_interval_show(struct device *dev) { struct sht3x_data *data = dev_get_drvdata(dev);- return sysfs_emit(buf, "%u\n",- mode_to_update_interval[data->mode]); + return mode_to_update_interval[data->mode]; }-static ssize_t update_interval_store(struct device *dev,- struct device_attribute *attr, - const char *buf, - size_t count) +static int update_interval_store(struct device *dev, const char *val) { u16 update_interval; u8 mode; @@ -582,7 +583,7 @@ static ssize_t update_interval_store(struct device *dev, struct sht3x_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client;- ret = kstrtou16(buf, 0, &update_interval);+ ret = kstrtou16(val, 0, &update_interval); if (ret) return ret;@@ -592,7 +593,7 @@ static ssize_t update_interval_store(struct device *dev,/* mode did not change */ if (mode == data->mode) { mutex_unlock(&data->data_lock); - return count; + return 0; }mutex_lock(&data->i2c_lock);@@ -634,7 +635,7 @@ static ssize_t update_interval_store(struct device *dev, if (ret != SHT3X_CMD_LENGTH) return ret < 0 ? ret : -EIO;- return count;+ return 0; }static ssize_t repeatability_show(struct device *dev,@@ -668,60 +669,191 @@ static ssize_t repeatability_store(struct device *dev, return count; }-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);-static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0); -static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max); -static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max); -static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst); -static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit, - limit_max_hyst); -static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min); -static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min); -static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst); -static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit, - limit_min_hyst); -static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0); -static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0); static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0); -static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0); static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0);static struct attribute *sht3x_attrs[] = {- &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_humidity1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_humidity1_max.dev_attr.attr, - &sensor_dev_attr_humidity1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_humidity1_min.dev_attr.attr, - &sensor_dev_attr_humidity1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_humidity1_alarm.dev_attr.attr, &sensor_dev_attr_heater_enable.dev_attr.attr, - &sensor_dev_attr_update_interval.dev_attr.attr, - &sensor_dev_attr_repeatability.dev_attr.attr, - NULL -}; - -static struct attribute *sts3x_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_heater_enable.dev_attr.attr, - &sensor_dev_attr_update_interval.dev_attr.attr, &sensor_dev_attr_repeatability.dev_attr.attr, NULL };ATTRIBUTE_GROUPS(sht3x);-ATTRIBUTE_GROUPS(sts3x);-static const struct i2c_device_id sht3x_ids[];+static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct sht3x_data *chip_data = data; + struct i2c_client *client = chip_data->client; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return 0644; + default: + return -EINVAL;return 0;+ } + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_alarm: + return 0444; + case hwmon_temp_max: + case hwmon_temp_max_hyst: + case hwmon_temp_min: + case hwmon_temp_min_hyst: + return 0644; + default: + return -EINVAL;return 0;+ } + case hwmon_humidity: + if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x) + return 0; + switch (attr) { + case hwmon_humidity_input: + case hwmon_humidity_alarm: + return 0444; + case hwmon_humidity_max: + case hwmon_humidity_max_hyst: + case hwmon_humidity_min: + case hwmon_humidity_min_hyst: + return 0644; + default: + return -EINVAL;return 0;+ } + default: + return -EINVAL;returen 0;+ } + + return -EINVAL;return 0; Never gets here. FWIW, you might use break; above instead of all those return 0; statements.+} + +static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + enum sht3x_limits index; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + *val = update_interval_show(dev); + break; + default: + return -EINVAL;-EOPNOTSUPP+ } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + *val = temp1_input_show(dev); + return 0; + case hwmon_temp_alarm: + *val = temp1_alarm_show(dev); + return 0; + case hwmon_temp_max: + index = limit_max; + break; + case hwmon_temp_max_hyst: + index = limit_max_hyst; + break; + case hwmon_temp_min: + index = limit_min; + break; + case hwmon_temp_min_hyst: + index = limit_min_hyst; + break; + default: + return -EINVAL;-EOPNOTSUPP+ } + *val = temp1_limit_show(dev, index); + return 0;Please be consistent. Either always return 0 in case statements or use break, but do not mix the two.
fix it
+ case hwmon_humidity: + switch (attr) { + case hwmon_humidity_input: + *val = humidity1_input_show(dev); + return 0; + case hwmon_humidity_alarm: + *val = humidity1_alarm_show(dev); + return 0; + case hwmon_humidity_max: + index = limit_max; + break; + case hwmon_humidity_max_hyst: + index = limit_max_hyst; + break; + case hwmon_humidity_min: + index = limit_min; + break; + case hwmon_humidity_min_hyst: + index = limit_min_hyst; + break; + default: + return -EINVAL;-EOPNOTSUPP+ } + *val = humidity1_limit_show(dev, index); + return 0; + default: + return -EINVAL;-EOPNOTSUPP+ } + + return 0; +} + +static int sht3x_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + enum sht3x_limits index; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return update_interval_store(dev, (const char *)&val); + default: + return -EINVAL;-EOPNOTSUPP+ } + case hwmon_temp: + switch (attr) { + case hwmon_temp_max: + index = limit_max; + break; + case hwmon_temp_max_hyst: + index = limit_max_hyst; + break; + case hwmon_temp_min: + index = limit_min; + break; + case hwmon_temp_min_hyst: + index = limit_min_hyst; + break; + default: + return -EINVAL;-EOPNOTSUPP+ } + return temp1_limit_store(dev, index, (const char *)&val); + case hwmon_humidity: + switch (attr) { + case hwmon_humidity_max: + index = limit_max; + break; + case hwmon_humidity_max_hyst: + index = limit_max_hyst; + break; + case hwmon_humidity_min: + index = limit_min; + break; + case hwmon_humidity_min_hyst: + index = limit_min_hyst; + break; + default: + return -EINVAL;-EOPNOTSUPP+ } + return humidity1_limit_store(dev, index, (const char *)val); + default: + return -EINVAL;-EOPNOTSUPP+ } +}static int sht3x_probe(struct i2c_client *client){ @@ -730,7 +862,6 @@ static int sht3x_probe(struct i2c_client *client) struct device *hwmon_dev; struct i2c_adapter *adap = client->adapter; struct device *dev = &client->dev; - const struct attribute_group **attribute_groups;/** we require full i2c support since the sht3x uses multi-byte read and @@ -771,15 +902,11 @@ static int sht3x_probe(struct i2c_client *client) if (ret) return ret;- if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x)- attribute_groups = sts3x_groups; - else - attribute_groups = sht3x_groups; - - hwmon_dev = devm_hwmon_device_register_with_groups(dev, - client->name, - data, - attribute_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, + client->name, + data, + &sht3x_chip_info, + sht3x_groups);Shouldn't sht3x_groups only be added if the chip is sts3x ?
all functionality are registered, but as for sts3x, humidity-related hwmon-interface
will be invisble.The code listed below is defined in sht3x_is_visble, I also notice that if return value
is zero, the attribute will not be created. case hwmon_humidity: + if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x) + return 0;
if (IS_ERR(hwmon_dev))dev_dbg(dev, "unable to register hwmon device\n"); -- 2.30.2