iio:core: mounting matrix support
Expose a rotation matrix to indicate userspace the chip placement with respect to the overall hardware system. This is needed to adjust coordinates sampled from a sensor chip when its position deviates from the main hardware system. Final coordinates computation is delegated to userspace since: * computation may involve floating point arithmetics ; * it allows an application to combine adjustments with arbitrary transformations. This 3 dimentional space rotation matrix is expressed as 3x3 array of strings to support floating point numbers. It may be retrieved from a "[<dir>_][<type>_]mount_matrix" sysfs attribute file. It is declared into a device / driver specific DTS property or platform data. Signed-off-by: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
parent
dc2c57153e
commit
dfc57732ad
|
@ -1512,3 +1512,54 @@ Contact: linux-iio@vger.kernel.org
|
|||
Description:
|
||||
Raw (unscaled no offset etc.) pH reading of a substance as a negative
|
||||
base-10 logarithm of hydrodium ions in a litre of water.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/mount_matrix
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_mount_matrix
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_mount_matrix
|
||||
KernelVersion: 4.6
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Mounting matrix for IIO sensors. This is a rotation matrix which
|
||||
informs userspace about sensor chip's placement relative to the
|
||||
main hardware it is mounted on.
|
||||
Main hardware placement is defined according to the local
|
||||
reference frame related to the physical quantity the sensor
|
||||
measures.
|
||||
Given that the rotation matrix is defined in a board specific
|
||||
way (platform data and / or device-tree), the main hardware
|
||||
reference frame definition is left to the implementor's choice
|
||||
(see below for a magnetometer example).
|
||||
Applications should apply this rotation matrix to samples so
|
||||
that when main hardware reference frame is aligned onto local
|
||||
reference frame, then sensor chip reference frame is also
|
||||
perfectly aligned with it.
|
||||
Matrix is a 3x3 unitary matrix and typically looks like
|
||||
[0, 1, 0; 1, 0, 0; 0, 0, -1]. Identity matrix
|
||||
[1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and main hardware
|
||||
are perfectly aligned with each other.
|
||||
|
||||
For example, a mounting matrix for a magnetometer sensor informs
|
||||
userspace about sensor chip's ORIENTATION relative to the main
|
||||
hardware.
|
||||
More specifically, main hardware orientation is defined with
|
||||
respect to the LOCAL EARTH GEOMAGNETIC REFERENCE FRAME where :
|
||||
* Y is in the ground plane and positive towards magnetic North ;
|
||||
* X is in the ground plane, perpendicular to the North axis and
|
||||
positive towards the East ;
|
||||
* Z is perpendicular to the ground plane and positive upwards.
|
||||
|
||||
An implementor might consider that for a hand-held device, a
|
||||
'natural' orientation would be 'front facing camera at the top'.
|
||||
The main hardware reference frame could then be described as :
|
||||
* Y is in the plane of the screen and is positive towards the
|
||||
top of the screen ;
|
||||
* X is in the plane of the screen, perpendicular to Y axis, and
|
||||
positive towards the right hand side of the screen ;
|
||||
* Z is perpendicular to the screen plane and positive out of the
|
||||
screen.
|
||||
Another example for a quadrotor UAV might be :
|
||||
* Y is in the plane of the propellers and positive towards the
|
||||
front-view camera;
|
||||
* X is in the plane of the propellers, perpendicular to Y axis,
|
||||
and positive towards the starboard side of the UAV ;
|
||||
* Z is perpendicular to propellers plane and positive upwards.
|
||||
|
|
|
@ -412,6 +412,88 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iio_enum_write);
|
||||
|
||||
static const struct iio_mount_matrix iio_mount_idmatrix = {
|
||||
.rotation = {
|
||||
"1", "0", "0",
|
||||
"0", "1", "0",
|
||||
"0", "0", "1"
|
||||
}
|
||||
};
|
||||
|
||||
static int iio_setup_mount_idmatrix(const struct device *dev,
|
||||
struct iio_mount_matrix *matrix)
|
||||
{
|
||||
*matrix = iio_mount_idmatrix;
|
||||
dev_info(dev, "mounting matrix not found: using identity...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
|
||||
const struct iio_chan_spec *chan, char *buf)
|
||||
{
|
||||
const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *)
|
||||
priv)(indio_dev, chan);
|
||||
|
||||
if (IS_ERR(mtx))
|
||||
return PTR_ERR(mtx);
|
||||
|
||||
if (!mtx)
|
||||
mtx = &iio_mount_idmatrix;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
|
||||
mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
|
||||
mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
|
||||
mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
|
||||
|
||||
/**
|
||||
* of_iio_read_mount_matrix() - retrieve iio device mounting matrix from
|
||||
* device-tree "mount-matrix" property
|
||||
* @dev: device the mounting matrix property is assigned to
|
||||
* @propname: device specific mounting matrix property name
|
||||
* @matrix: where to store retrieved matrix
|
||||
*
|
||||
* If device is assigned no mounting matrix property, a default 3x3 identity
|
||||
* matrix will be filled in.
|
||||
*
|
||||
* Return: 0 if success, or a negative error code on failure.
|
||||
*/
|
||||
#ifdef CONFIG_OF
|
||||
int of_iio_read_mount_matrix(const struct device *dev,
|
||||
const char *propname,
|
||||
struct iio_mount_matrix *matrix)
|
||||
{
|
||||
if (dev->of_node) {
|
||||
int err = of_property_read_string_array(dev->of_node,
|
||||
propname, matrix->rotation,
|
||||
ARRAY_SIZE(iio_mount_idmatrix.rotation));
|
||||
|
||||
if (err == ARRAY_SIZE(iio_mount_idmatrix.rotation))
|
||||
return 0;
|
||||
|
||||
if (err >= 0)
|
||||
/* Invalid number of matrix entries. */
|
||||
return -EINVAL;
|
||||
|
||||
if (err != -EINVAL)
|
||||
/* Invalid matrix declaration format. */
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Matrix was not declared at all: fallback to identity. */
|
||||
return iio_setup_mount_idmatrix(dev, matrix);
|
||||
}
|
||||
#else
|
||||
int of_iio_read_mount_matrix(const struct device *dev,
|
||||
const char *propname,
|
||||
struct iio_mount_matrix *matrix)
|
||||
{
|
||||
return iio_setup_mount_idmatrix(dev, matrix);
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL(of_iio_read_mount_matrix);
|
||||
|
||||
/**
|
||||
* iio_format_value() - Formats a IIO value into its string representation
|
||||
* @buf: The buffer to which the formatted value gets written
|
||||
|
|
|
@ -147,6 +147,37 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
|
|||
.private = (uintptr_t)(_e), \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iio_mount_matrix - iio mounting matrix
|
||||
* @rotation: 3 dimensional space rotation matrix defining sensor alignment with
|
||||
* main hardware
|
||||
*/
|
||||
struct iio_mount_matrix {
|
||||
const char *rotation[9];
|
||||
};
|
||||
|
||||
ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
|
||||
const struct iio_chan_spec *chan, char *buf);
|
||||
int of_iio_read_mount_matrix(const struct device *dev, const char *propname,
|
||||
struct iio_mount_matrix *matrix);
|
||||
|
||||
typedef const struct iio_mount_matrix *
|
||||
(iio_get_mount_matrix_t)(const struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan);
|
||||
|
||||
/**
|
||||
* IIO_MOUNT_MATRIX() - Initialize mount matrix extended channel attribute
|
||||
* @_shared: Whether the attribute is shared between all channels
|
||||
* @_get: Pointer to an iio_get_mount_matrix_t accessor
|
||||
*/
|
||||
#define IIO_MOUNT_MATRIX(_shared, _get) \
|
||||
{ \
|
||||
.name = "mount_matrix", \
|
||||
.shared = (_shared), \
|
||||
.read = iio_show_mount_matrix, \
|
||||
.private = (uintptr_t)(_get), \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iio_event_spec - specification for a channel event
|
||||
* @type: Type of the event
|
||||
|
|
Loading…
Reference in New Issue