iio: Fix iio_fixup_sampling_frequency() picking an unsupported sampling_frequency
Some iio drivers only accept sampling_frequency values listed in sampling_frequency_available and will reject any other values with an EINVAL error. This causes iio_fixup_sampling_frequency() to fail to fixup the sampling rate making screen-rotation really really slow on e.g. devices where the st_accel driver is used. Add support for parsing sampling_frequency_available and pick a value from there to fix this. As part of this also switch to using g_ascii_dtostr() to format the string to write so that numbers which are not whole can be represented.
This commit is contained in:

committed by
Bastien Nocera

parent
c8b528b020
commit
b888499f50
@@ -13,7 +13,10 @@
|
||||
#include "iio-buffer-utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -547,6 +550,61 @@ process_scan_1 (char *data,
|
||||
g_warning ("IIO channel '%s' could not be found", ch_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* iio_round_sampling_frequency: Round sampling_frequency to a supported value
|
||||
* @dev: the IIO device to round the sampling frequency for
|
||||
* @name: name of the *sampling_frequency attribute for which to round value
|
||||
* @desired: desired value
|
||||
*
|
||||
* Check "<name>_available" and if that attribute exists round the desired
|
||||
* value to a supported value, rounding up where possible.
|
||||
*/
|
||||
static double
|
||||
iio_round_sampling_frequency (GUdevDevice *dev, const char *name, double desired)
|
||||
{
|
||||
g_autofree char *available_attr = NULL;
|
||||
const char *available_str;
|
||||
char *endptr;
|
||||
double closest_higher = DBL_MAX;
|
||||
double closest_lower = 0.0;
|
||||
double available;
|
||||
|
||||
available_attr = g_strconcat (name, "_available", NULL);
|
||||
available_str = g_udev_device_get_sysfs_attr (dev, available_attr);
|
||||
|
||||
if (!available_str)
|
||||
return desired;
|
||||
|
||||
while (*available_str) {
|
||||
available = g_ascii_strtod (available_str, &endptr);
|
||||
if (available_str == endptr || (*endptr && !isspace (*endptr)))
|
||||
break;
|
||||
|
||||
available_str = endptr;
|
||||
|
||||
/* 0 disables sampling, skip */
|
||||
if (available == 0.0)
|
||||
continue;
|
||||
|
||||
if (available >= desired) {
|
||||
if (available < closest_higher)
|
||||
closest_higher = available;
|
||||
} else {
|
||||
if (available > closest_lower)
|
||||
closest_lower = available;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prefer higher values */
|
||||
if (closest_higher != DBL_MAX)
|
||||
return closest_higher;
|
||||
|
||||
if (closest_lower != 0.0)
|
||||
return closest_lower;
|
||||
|
||||
return desired;
|
||||
}
|
||||
|
||||
/**
|
||||
* iio_fixup_sampling_frequency: Fixup devices *sampling_frequency attributes
|
||||
* @dev: the IIO device to fix the sampling frequencies for
|
||||
@@ -566,6 +624,7 @@ iio_fixup_sampling_frequency (GUdevDevice *dev)
|
||||
const char *device_dir;
|
||||
const char *name;
|
||||
g_autoptr(GError) error = NULL;
|
||||
char sample_freq_str[G_ASCII_DTOSTR_BUF_SIZE];
|
||||
double sample_freq;
|
||||
|
||||
device_dir = g_udev_device_get_sysfs_path (dev);
|
||||
@@ -583,8 +642,16 @@ iio_fixup_sampling_frequency (GUdevDevice *dev)
|
||||
if (sample_freq >= IIO_MIN_SAMPLING_FREQUENCY)
|
||||
continue; /* Continue with pre-set sample freq. */
|
||||
|
||||
/* Sample freq too low, set it to 10Hz */
|
||||
if (write_sysfs_int (name, device_dir, IIO_MIN_SAMPLING_FREQUENCY) < 0)
|
||||
/* Sample freq too low, set it to a supported freq close to 10Hz */
|
||||
sample_freq = iio_round_sampling_frequency (dev, name, IIO_MIN_SAMPLING_FREQUENCY);
|
||||
|
||||
/*
|
||||
* Some sample_freq IIO sysfs attr only accept integers, most will
|
||||
* accept floats but not all. g_ascii_dtostr() uses the shortest
|
||||
* possible representation, omitting the "." for whole numbers.
|
||||
*/
|
||||
g_ascii_dtostr (sample_freq_str, G_ASCII_DTOSTR_BUF_SIZE, sample_freq);
|
||||
if (write_sysfs_string (name, device_dir, sample_freq_str) < 0)
|
||||
g_warning ("Could not fix sample-freq for %s/%s", device_dir, name);
|
||||
}
|
||||
g_dir_close (dir);
|
||||
|
Reference in New Issue
Block a user