Re: [PATCH RFC v2 3/4] iio: core: use kstrtodec64() to parse fixed-point values
From: Rodrigo Alencar
Date: Wed Oct 14 2026 - 06:54:16 EST
On 13/10/26 22:08, Andy Shevchenko wrote:
> On Tue, Oct 13, 2026 at 10:36:46AM -0300, Rodrigo Alencar via B4 Relay wrote:
>
> > Replace the open-coded __iio_str_to_fixpoint() parser with kstrtodec64(),
> > so sysfs writes of fixed-point values also accept E notation.
> >
> > The fractional part only keeps the sign when the integer part is zero,
> > as before. The dB suffix for scale attributes is now handled by a separate
> > iio_str_to_fixpoint_units() helper. It strips an optional trailing newline
> > and the "dB" or " dB" suffix before parsing.
> >
> > When there is no fractional part (fract_mult == 0, or dec_scale == 0 for
> > 64-bit values), try base-autodetecting kstrtoll() first so hexadecimal
> > and octal input keeps its meaning ("010" is still 8). Fall back to
> > kstrtodec64() on -EINVAL to accept E notation.
> >
> > As a side effect, inputs that used to be rejected for integer-only
> > attributes are now accepted. An invalid octal number such as "08" is
> > parsed as decimal 8, and a fractional value such as "1.5" is truncated
> > to 1, matching how kstrtodec64() drops digits beyond the requested
> > scale.
...
> > +static int iio_str_to_fixpoint_units(const char *str, const char *units,
> > + int fract_mult, int *integer, int *fract)
> > +{
> > + size_t units_len = strlen(units);
> > + size_t num_len = strlen(str);
> > + const char *dec_str = str;
> > + char buf[64];
before strncmp(), num_len is adjusted to skip '\n'
> > + if (num_len && str[num_len - 1] == '\n')
> > + num_len--;
> > + if (num_len > units_len &&
> > + !strncmp(str + num_len - units_len, units, units_len)) {
>
> Hmm... We have strends()... Do you expect string to have garbage at the end?
> In such a case dB and dBm won't be distinguishable.
It might end with '\n' (see above). It would have to test for both
"dB" and "dB\n" with strends(), having to prepare a separate buffer
just for "dB\n".
The current logic will not accept "dBm" in case units = "dB".
because it would compare "dB" with "Bm" from "dBm", i.e. an input of
"10 dBm\n" would fail comparison and pass "10 dBm\n" (original string)
to iio_str_to_fixpoint(), which would fail for EINVAL.
Another fail case would be "10 ddB\n", which would pass the comparison,
having "10 d" passed to iio_str_to_fixpoint(), which again, will fail
for EINVAL.
Will add the requested test case.
> > + num_len -= units_len;
before the memcpy() num_len is adjusted again to skip ' '
> > + if (str[num_len - 1] == ' ')
> > + num_len--;
> > + if (num_len >= sizeof(buf))
> > + return -EINVAL;
> > + memcpy(buf, str, num_len);
> > + buf[num_len] = '\0';
> > + dec_str = buf;
> > + }
> > +
> > + return iio_str_to_fixpoint(dec_str, fract_mult, integer, fract);
> > +}
--
Kind regards,
Rodrigo Alencar