Some parameters have a maximum that's below the maximum value allowed by the type, which would be convenient to set as percentage, e.g. volume of a sound card or brightness level of a backlight.
With the new simple_strtofract, we can easily accomplish this, so add support for that. Signed-off-by: Ahmad Fatoum <[email protected]> --- include/param.h | 8 ++++++++ lib/parameter.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/include/param.h b/include/param.h index a15e064ddec2..59aa8a3a385f 100644 --- a/include/param.h +++ b/include/param.h @@ -116,6 +116,8 @@ void param_remove(struct param_d *p); int bobject_param_set_generic(bobject_t bobj, struct param_d *p, const char *val); +int param_int_set_scale(struct param_d *p, uint64_t max); + #else static inline const char *bobject_get_param(bobject_t bobj, const char *name) { @@ -251,6 +253,12 @@ static inline int bobject_param_set_generic(bobject_t bobj, struct param_d *p, { return 0; } + +static inline int param_int_set_scale(struct param_d *p, uint64_t max) +{ + return 0; +} + #endif static inline const char *get_param_value(struct param_d *param) diff --git a/lib/parameter.c b/lib/parameter.c index 274e6fcb8376..f36d77d119fa 100644 --- a/lib/parameter.c +++ b/lib/parameter.c @@ -354,6 +354,7 @@ struct param_int { const char *format; int (*set)(struct param_d *p, void *priv); int (*get)(struct param_d *p, void *priv); + u64 scale_max; }; static inline struct param_int *to_param_int(struct param_d *p) @@ -403,6 +404,33 @@ static int param_int_set(struct bobject *bobj, struct param_d *p, return ret; } +static int param_int_set_scaled(struct bobject *bobj, struct param_d *p, + const char *val) +{ + char buf[sizeof("18446744073709551615")]; + struct param_int *pi = to_param_int(p); + s64 scaled; + char *end; + + if (!isempty(val) && val[strlen(val) - 1] == '%') { + u64 percent = div_u64(pi->scale_max, 100); + + scaled = simple_strtofract(val, &end, percent); + if (val == end || *end != '%' || + scaled < 0 || scaled > percent * 100) + return -EINVAL; + + /* saturate at 100% */ + if (scaled == percent * 100) + scaled = pi->scale_max; + + snprintf(buf, sizeof(buf), pi->format, scaled); + val = buf; + } + + return param_int_set(bobj, p, val); +} + static const char *param_int_get(struct bobject *bobj, struct param_d *p) { struct param_int *pi = to_param_int(p); @@ -432,6 +460,24 @@ static const char *param_int_get(struct bobject *bobj, struct param_d *p) return p->value; } +static void param_int_max_info(struct param_d *p) +{ + struct param_int *pi = to_param_int(p); + printf(" (maximum: %llu)", pi->scale_max); +} + +int param_int_set_scale(struct param_d *p, uint64_t max) +{ + if (IS_ERR(p)) + return PTR_ERR(p); + + p->info = param_int_max_info; + p->set = param_int_set_scaled; + to_param_int(p)->scale_max = max; + + return 0; +} + int param_set_readonly(struct param_d *p, void *priv) { return -EROFS; -- 2.47.3
