Re: [PATCH] iio/hid: Add mount_matrix

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 6/25/22 22:52, Gwendal Grignou wrote:
> On Sat, Jun 25, 2022 at 11:27 AM srinivas pandruvada
> <srinivas.pandruvada@xxxxxxxxxxxxxxx> wrote:
>>
>> On Sat, 2022-06-25 at 14:33 +0200, Hans de Goede wrote:
>>> Hi,
>>>
>>> Jonathan, thanks for Cc-ing me on this.
>>>
>>> On 6/25/22 13:09, Jonathan Cameron wrote:
>>>> On Fri, 24 Jun 2022 15:33:41 -0700
>>>> Gwendal Grignou <gwendal@xxxxxxxxxxxx> wrote:
>>>>
>>>>> ISH based sensors do not naturally return data in the W3C
>>>>> 'natural'
>>>>> orientation.
>>>>> They returns all data inverted, to match Microsoft Windows
>>>>> requirement:
>>>>> [
>>>>> https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/senso
>>>>> rs#accelerometer]
>>>>> """ If the device has the SimpleOrientation of FaceUp on a table,
>>>>> then
>>>>> the accelerometer would read -1 G on the Z axis. """
>>>>
>>>> Probably reference the HID Usage Tables 1.3 spec rather than the MS
>>>> one.
>>>> https://usb.org/sites/default/files/hut1_3_0.pdf
> That document does not clearly defined what the accelerometer should return.
>>>> After some waving around of my left and right hand I'm fairly sure
>>>> that says the same
>>>> thing as the MS spec. Section 4.4 Vector Usages
>>>>
>>>>> While W3C defines
>>>>> [https://www.w3.org/TR/motion-sensors/#accelerometer-sensor]
>>>>> """The Accelerometer sensor is an inertial-frame sensor, this
>>>>> means that
>>>>> when the device is in free fall, the acceleration is 0 m/s2 in
>>>>> the
>>>>> falling direction, and when a device is laying flat on a table,
>>>>> the
>>>>> acceleration in upwards direction will be equal to the Earth
>>>>> gravity,
>>>>> i.e. g ≡ 9.8 m/s2 as it is measuring the force of the table
>>>>> pushing the
>>>>> device upwards."""
>>>>>
>>>>> Fixes all HID sensors that defines IIO_MOD_[XYZ] attributes.
>>>>>
>>>>> Tested on "HP Spectre x360 Convertible 13" and "Dell XPS 13
>>>>> 9365".
>>>>>
>>>>> Signed-off-by: Gwendal Grignou <gwendal@xxxxxxxxxxxx>
>>>>
>>>> Ah.  Whilst this is a fix, it seems likely to break a whole bunch
>>>> of existing
>>>> users that are compensating for the wrong orientation in
>>>> userspace.  Also, do
>>>> we know how universal this is?  I have a nasty feeling it'll turn
>>>> out some
>>>> HID sensors do it the other way whatever the spec says.  Bastien,
>>>> are you
>>>> carrying a local fix for this in your userspace code?
>>>>
>>>> +CC a few people who are likely to know more on just how bad that
>>>> will be...
>>>
>>> Right, so Linux userspace expects an axis system similar to the
>>> Android one,
>>> which is actually the one which seems to be described here.
>>>
>>> The axis system expect is that when a tablet is layed flat on the
>>> table,
>>> the x and y axis are as one would expect when drawing a mathematics
>>> graph on the surface of the tablet.
>>>
>>> So X-axis goes from left to right, with left side being lower numbers
>>> and
>>> right side higher numbers.
>>>
>>> And Y-axis goes from bottom to top, with the bottom being lower
>>> numbers and
>>> the top higher numbers.
>>>
>>> That leaves the Z-axis which comes out of the screen at a 90° angle
>>> (to both
>>> the X and Y axis) and the vector coming out of the screen towards to
>>> the user /
>>> observer of the screen indicates positive numbers where as imagining
>>> the same
>>> axis pointing down through the table on which the tables is lying
>>> towards
>>> the floor represents negative numbers.
>>>
>>> This means that the accel values of a tablet resting on a table,
>>> expresses
>>> in units of 1G are: [ 0, 0, -1 ] and I've seen quite a few HID
>>> sensors
> But W3C and Android expect [ 0, 0, 1g ] when resting on the table. See
> commit message for W3C and for Android, see
> https://source.android.com/devices/sensors/sensor-types#accelerometer
> """When the device lies flat on a table, the acceleration value along
> z is +9.81 alo, which corresponds to the acceleration of the device (0
> m/s^2) minus the force of gravity (-9.81 m/s^2)."""". That is why we
> need to change the sign to be consistent with these standards.

Windows and HID devices use [ 0, 0, -1 ] for device face up on
a flat table and this is what Linux has been reporting to userspace
for many many years now. Auto-display-rotation based in accel
reading was first supported in GNOME through iio-sensor-proxy
in 2014 !

And iio-sensor-proxy expects the Windows/HID sign of the axis
you can NOT just go and change this, that would break 8 years
of precedent of using the current Windows/HID sign (+/-) for
the axis!

Also besides the kernel reporting a matrix it is also possible
for userspace to provide a matrix using udev's hwdb:

https://github.com/systemd/systemd/blob/main/hwdb.d/60-sensor.hwdb

This has been in place since 2016 and this sets a matrix adjusting
readings of non HID sensors to match the *HID/windows* definition
of the axis.

>>> with accel reporting on various devices and they all adhere to this
>>> without applying any accel matrix. Or in other words, HID sensors
>>> behave
>>> as expected by userspace when applying the norm matrix of:
>>>
>>>         .rotation = {
>>>                 "1", "0", "0",
>>>                 "0", "1", "0",
>>>                 "0", "0", "1"
>>>
>>> And this patch will cause the image to be upside down (no matter what
>>> the
>>> rotation) when using auto-rotation with iio-sensor-proxy.
>>>
>>> So big NACK from me for this patch.
>>>
>>> I'm not sure what this patch is trying to fix but it looks to me like
>>> it
>>> is a bug in the HID sensors implementation of the specific device.
> This is a not a bug since HID sensors from 2 laptops from different
> manufacturers (HP and Dell) report the same values.

Right, I wrongly assumed the Android definition would match the
IMHO much saner / much more intuitive HID/Windows definitions,
since the arrows in the phone image in the Android docs point
in the same direction as the Windows docs.

But I have tested on an Android phone now and I see that
Android indeed has all the axis inverted.
 
>>> Again HID-sensors already work fine on tons of existing devices
>>> without
>>> any matrix getting applied.
> Note this patch does not change the value reported by the sensor, just
> define a matrix to make sure the sensors values are consistent with
> Android/W3C.

And iio-sensor-proxy will read the kernel provided matrix, apply it
and then put the image upside down since you've just mirrored both
the X and Y axis, breaking rotation for all existing GNOME and KDE
users.

So still a big NACK from me.

If Android needs the axis to be flipped, then it should do so
in the iio-sensor HAL inside android, not add a matrix which
breaks 8 years of userspace API convention.

Breaking userspace is simply not acceptible, we have a very clear
no regressions policy. So this patch simply cannot be merged: NACK.

Regards,

Hans




>>>> One other thing inline.  The mount matrix you've provided isn't a
>>>> rotation matrix.
>>>>
>>>> I'd forgotten the annoyance of graphics folks using the right
>>>> handed sensor
>>>> axis whilst nearly all other uses are left handed. It drove me mad
>>>> many years
>>>> ago - every code base that used sensors and rendered the result
>>>> needed a
>>>> flip of the z axis - it was never well documented, so half the time
>>>> the code ended up with many axis flips based on people debugging
>>>> local
>>>> orientation problems.  *sigh*
>>>>
>>>>
>>>>> ---
>>>>>  drivers/iio/accel/hid-sensor-accel-3d.c       |  3 +++
>>>>>  .../hid-sensors/hid-sensor-attributes.c       | 21
>>>>> +++++++++++++++++++
>>>>>  drivers/iio/gyro/hid-sensor-gyro-3d.c         |  3 +++
>>>>>  drivers/iio/magnetometer/hid-sensor-magn-3d.c |  3 +++
>>>>>  include/linux/hid-sensor-hub.h                |  2 ++
>>>>>  5 files changed, 32 insertions(+)
>>>>>
>>>>> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c
>>>>> b/drivers/iio/accel/hid-sensor-accel-3d.c
>>>>> index a2def6f9380a3..980bbd7fba502 100644
>>>>> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
>>>>> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
>>>>> @@ -59,6 +59,7 @@ static const struct iio_chan_spec
>>>>> accel_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_X,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_ACCEL,
>>>>>                 .modified = 1,
>>>>> @@ -69,6 +70,7 @@ static const struct iio_chan_spec
>>>>> accel_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_Y,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_ACCEL,
>>>>>                 .modified = 1,
>>>>> @@ -79,6 +81,7 @@ static const struct iio_chan_spec
>>>>> accel_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_Z,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         },
>>>>>         IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
>>>>>  };
>>>>> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-
>>>>> attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-
>>>>> attributes.c
>>>>> index 9b279937a24e0..e367e4b482ef0 100644
>>>>> --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
>>>>> +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
>>>>> @@ -585,6 +585,27 @@ int
>>>>> hid_sensor_parse_common_attributes(struct hid_sensor_hub_device
>>>>> *hsdev,
>>>>>  }
>>>>>  EXPORT_SYMBOL_NS(hid_sensor_parse_common_attributes, IIO_HID);
>>>>>
>>>>> +static const struct iio_mount_matrix hid_sensor_windows_axis = {
>>>>> +       .rotation = {
>>>>> +               "-1", "0", "0",
>>>>> +               "0", "-1", "0",
>>>>> +               "0", "0", "-1"
>>>>
>>>> Unless my memory of rotation matrices serves me wrong, that's not a
>>>> rotation matrix.
>>>> (det(R) != 1)
> This is indeed not a rotation matrix.
> What I observed is when laying flat on the table (open at 180 degree),
> using the sysfs interface the value reported by the laptops along the
> Z axis is -1g, while using an android phone, the reported value is 1g.
> Same thing when the device is lying on this left side (reported value
> along the X axis -1g instead of 1g for an android phone), and when
> resting on the front lip (reported value along the Y axis is -1g
> instead of 1g).
> 
>>>>
>>>> That's a an axis flip from a right handed set of axis to a left
>>>> handed one.
>>>> So to fix this up, you would need to invert the raw readings of at
>>>> least one axis
>>>> rather than rely on the mount matrix or make the scale negative.
> Negative scale is a good option, but it will definitely break user
> space applications, when the mount matrix may not be used today.
> 
> Gwendal.
>>>>
>>>> Jonathan
>>>>
>>>>
>>>>> +       }
>>>>> +};
>>>>> +
>>>>> +static const struct iio_mount_matrix *
>>>>> +hid_sensor_get_mount_matrix(const struct iio_dev *indio_dev,
>>>>> +                               const struct iio_chan_spec *chan)
>>>>> +{
>>>>> +       return &hid_sensor_windows_axis;
>>>>> +}
>>>>> +
>>>>> +const struct iio_chan_spec_ext_info hid_sensor_ext_info[] = {
>>>>> +       IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE,
>>>>> hid_sensor_get_mount_matrix),
>>>>> +       { }
>>>>> +};
>>>>> +EXPORT_SYMBOL(hid_sensor_ext_info);
>>>>> +
>>>>>  MODULE_AUTHOR("Srinivas Pandruvada
>>>>> <srinivas.pandruvada@xxxxxxxxx>");
>>>>>  MODULE_DESCRIPTION("HID Sensor common attribute processing");
>>>>>  MODULE_LICENSE("GPL");
>>>>> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c
>>>>> b/drivers/iio/gyro/hid-sensor-gyro-3d.c
>>>>> index 8f0ad022c7f1b..b852f5166bb21 100644
>>>>> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
>>>>> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
>>>>> @@ -58,6 +58,7 @@ static const struct iio_chan_spec
>>>>> gyro_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_X,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_ANGL_VEL,
>>>>>                 .modified = 1,
>>>>> @@ -68,6 +69,7 @@ static const struct iio_chan_spec
>>>>> gyro_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_Y,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_ANGL_VEL,
>>>>>                 .modified = 1,
>>>>> @@ -78,6 +80,7 @@ static const struct iio_chan_spec
>>>>> gyro_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>>                 .scan_index = CHANNEL_SCAN_INDEX_Z,
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         },
>>>>>         IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
>>>>>  };
>>>>> diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
>>>>> b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
>>>>> index e85a3a8eea908..aefbdb9b0869a 100644
>>>>> --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
>>>>> +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
>>>>> @@ -74,6 +74,7 @@ static const struct iio_chan_spec
>>>>> magn_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SCALE) |
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_MAGN,
>>>>>                 .modified = 1,
>>>>> @@ -83,6 +84,7 @@ static const struct iio_chan_spec
>>>>> magn_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SCALE) |
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_MAGN,
>>>>>                 .modified = 1,
>>>>> @@ -92,6 +94,7 @@ static const struct iio_chan_spec
>>>>> magn_3d_channels[] = {
>>>>>                 BIT(IIO_CHAN_INFO_SCALE) |
>>>>>                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
>>>>>                 BIT(IIO_CHAN_INFO_HYSTERESIS),
>>>>> +               .ext_info = hid_sensor_ext_info,
>>>>>         }, {
>>>>>                 .type = IIO_ROT,
>>>>>                 .modified = 1,
>>>>> diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-
>>>>> sensor-hub.h
>>>>> index c27329e2a5ad5..ee7d5b430a785 100644
>>>>> --- a/include/linux/hid-sensor-hub.h
>>>>> +++ b/include/linux/hid-sensor-hub.h
>>>>> @@ -236,6 +236,8 @@ struct hid_sensor_common {
>>>>>         struct work_struct work;
>>>>>  };
>>>>>
>>>>> +extern const struct iio_chan_spec_ext_info
>>>>> hid_sensor_ext_info[];
>>>>> +
>>>>>  /* Convert from hid unit expo to regular exponent */
>>>>>  static inline int hid_sensor_convert_exponent(int unit_expo)
>>>>>  {
>>>>
>>>
>>
> 




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux