*val2 = rem / (int)tmp; if (rem2)
*val2 += div_s64((s64)rem2 * 1000000000LL, tmp);
return IIO_VAL_INT_PLUS_NANO; case IIO_VAL_INT_PLUS_NANO: case IIO_VAL_INT_PLUS_MICRO:
mult = scale_type == IIO_VAL_INT_PLUS_NANO ? 1000000000L : 1000000L;
/* * For IIO_VAL_INT_PLUS_{MICRO,NANO} scale types if either *val * OR *val2 is negative the schan scale is negative, i.e. * *val = 1 and *val2 = -0.5 yields -1.5 not -0.5.
*/
neg = *val < 0 || *val2 < 0;
/* * If only one of the rescaler elements or the schan scale is * negative, the combined scale is negative.
*/ if (neg ^ ((rescale->numerator < 0) ^ (rescale->denominator < 0))) { if (*val)
*val = -*val; else
*val2 = -*val2;
}
staticint rescale_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct rescale *rescale = iio_priv(indio_dev); int scale, scale2; int schan_off = 0; int ret;
switch (mask) { case IIO_CHAN_INFO_RAW: if (rescale->chan_processed) /* * When only processed channels are supported, we * read the processed data and scale it by 1/1 * augmented with whatever the rescaler has calculated.
*/ return iio_read_channel_processed(rescale->source, val); else return iio_read_channel_raw(rescale->source, val);
case IIO_CHAN_INFO_SCALE: if (rescale->chan_processed) { /* * Processed channels are scaled 1-to-1
*/
*val = 1;
*val2 = 1;
ret = IIO_VAL_FRACTIONAL;
} else {
ret = iio_read_channel_scale(rescale->source, val, val2);
} return rescale_process_scale(rescale, ret, val, val2); case IIO_CHAN_INFO_OFFSET: /* * Processed channels are scaled 1-to-1 and source offset is * already taken into account. * * In other cases, real world measurement are expressed as: * * schan_scale * (raw + schan_offset) * * Given that the rescaler parameters are applied recursively: * * rescaler_scale * (schan_scale * (raw + schan_offset) + * rescaler_offset) * * Or, * * (rescaler_scale * schan_scale) * (raw + * (schan_offset + rescaler_offset / schan_scale) * * Thus, reusing the original expression the parameters exposed * to userspace are: * * scale = schan_scale * rescaler_scale * offset = schan_offset + rescaler_offset / schan_scale
*/ if (rescale->chan_processed) {
*val = rescale->offset; return IIO_VAL_INT;
}
if (iio_channel_has_info(rescale->source->channel,
IIO_CHAN_INFO_OFFSET)) {
ret = iio_read_channel_offset(rescale->source,
&schan_off, NULL); if (ret != IIO_VAL_INT) return ret < 0 ? ret : -EOPNOTSUPP;
}
if (iio_channel_has_info(rescale->source->channel,
IIO_CHAN_INFO_SCALE)) {
ret = iio_read_channel_scale(rescale->source, &scale, &scale2); return rescale_process_offset(rescale, ret, scale, scale2,
schan_off, val, val2);
}
/* * If we get here we have no scale so scale 1:1 but apply * rescaler and offset, if any.
*/ return rescale_process_offset(rescale, IIO_VAL_FRACTIONAL, 1, 1,
schan_off, val, val2); default: return -EINVAL;
}
}
staticint rescale_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, constint **vals, int *type, int *length, long mask)
{ struct rescale *rescale = iio_priv(indio_dev);
if (rescale->offset)
chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OFFSET);
/* * Using .read_avail() is fringe to begin with and makes no sense * whatsoever for processed channels, so we make sure that this cannot * be called on a processed channel.
*/ if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW) &&
!rescale->chan_processed)
chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW);
ret = device_property_read_u32(dev, "sense-resistor-micro-ohms",
&sense); if (ret) {
dev_err(dev, "failed to read the sense resistance: %d\n", ret); return ret;
}
ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms",
&shunt); if (ret) {
dev_err(dev, "failed to read the shunt resistance: %d\n", ret); return ret;
}
staticint rescale_probe(struct platform_device *pdev)
{ struct device *dev = &pdev->dev; struct iio_dev *indio_dev; struct iio_channel *source; struct rescale *rescale; int sizeof_ext_info; int sizeof_priv; int i; int ret;
source = devm_iio_channel_get(dev, NULL); if (IS_ERR(source)) return dev_err_probe(dev, PTR_ERR(source), "failed to get source channel\n");
sizeof_ext_info = iio_get_channel_ext_info_count(source); if (sizeof_ext_info) {
sizeof_ext_info += 1; /* one extra entry for the sentinel */
sizeof_ext_info *= sizeof(*rescale->ext_info);
}
sizeof_priv = sizeof(*rescale) + sizeof_ext_info;
indio_dev = devm_iio_device_alloc(dev, sizeof_priv); if (!indio_dev) return -ENOMEM;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.