public inbox for linux-iio@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
@ 2018-10-31 14:20 Hans de Goede
  2018-10-31 14:21 ` Hans de Goede
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Hans de Goede @ 2018-10-31 14:20 UTC (permalink / raw)
  To: Srinivas Pandruvada, Jonathan Cameron, Jiri Kosina,
	Benjamin Tissoires
  Cc: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio, linux-input

Before this commit sensor_hub_input_attr_get_raw_value() failed to take
the signedness of 16 and 8 bit values into account, returning e.g.
65436 instead of -100 for the z-axis reading of an accelerometer.

This commit adds a new is_signed parameter to the function and makes all
callers pass the appropriate value for this.

While at it, this commit also fixes up some neighboring lines where
statements were needlessly split over 2 lines to improve readability.

Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-Adjust the kernel doc for the new is_signed parameter to
 sensor_hub_input_attr_get_raw_value()
-Add Srinivas' Acked-by
---
 drivers/hid/hid-sensor-custom.c                  |  2 +-
 drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++---
 drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
 drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
 drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
 drivers/iio/light/hid-sensor-als.c               |  8 +++++---
 drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
 drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
 drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
 drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
 drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
 drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
 include/linux/hid-sensor-hub.h                   |  4 +++-
 13 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
index e8a114157f87..bb012bc032e0 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
 						sensor_inst->hsdev,
 						sensor_inst->hsdev->usage,
 						usage, report_id,
-						SENSOR_HUB_SYNC);
+						SENSOR_HUB_SYNC, false);
 	} else if (!strncmp(name, "units", strlen("units")))
 		value = sensor_inst->fields[field_index].attribute.units;
 	else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 2b63487057c2..4256fdc5cd6d 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 					u32 usage_id,
 					u32 attr_usage_id, u32 report_id,
-					enum sensor_hub_read_flags flag)
+					enum sensor_hub_read_flags flag,
+					bool is_signed)
 {
 	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
 	unsigned long flags;
@@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 						&hsdev->pending.ready, HZ*5);
 		switch (hsdev->pending.raw_size) {
 		case 1:
-			ret_val = *(u8 *)hsdev->pending.raw_data;
+			if (is_signed)
+				ret_val = *(s8 *)hsdev->pending.raw_data;
+			else
+				ret_val = *(u8 *)hsdev->pending.raw_data;
 			break;
 		case 2:
-			ret_val = *(u16 *)hsdev->pending.raw_data;
+			if (is_signed)
+				ret_val = *(s16 *)hsdev->pending.raw_data;
+			else
+				ret_val = *(u16 *)hsdev->pending.raw_data;
 			break;
 		case 4:
 			ret_val = *(u32 *)hsdev->pending.raw_data;
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 41d97faf5013..38ff374a3ca4 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 	struct hid_sensor_hub_device *hsdev =
 					accel_state->common_attributes.hsdev;
 
@@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_RAW:
 		hid_sensor_power_state(&accel_state->common_attributes, true);
 		report_id = accel_state->accel[chan->scan_index].report_id;
+		min = accel_state->accel[chan->scan_index].logical_minimum;
 		address = accel_3d_addresses[chan->scan_index];
 		if (report_id >= 0)
 			*val = sensor_hub_input_attr_get_raw_value(
 					accel_state->common_attributes.hsdev,
 					hsdev->usage, address, report_id,
-					SENSOR_HUB_SYNC);
+					SENSOR_HUB_SYNC,
+					min < 0);
 		else {
 			*val = 0;
 			hid_sensor_power_state(&accel_state->common_attributes,
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 36941e69f959..88e857c4baf4 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
@@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_RAW:
 		hid_sensor_power_state(&gyro_state->common_attributes, true);
 		report_id = gyro_state->gyro[chan->scan_index].report_id;
+		min = gyro_state->gyro[chan->scan_index].logical_minimum;
 		address = gyro_3d_addresses[chan->scan_index];
 		if (report_id >= 0)
 			*val = sensor_hub_input_attr_get_raw_value(
 					gyro_state->common_attributes.hsdev,
 					HID_USAGE_SENSOR_GYRO_3D, address,
 					report_id,
-					SENSOR_HUB_SYNC);
+					SENSOR_HUB_SYNC,
+					min < 0);
 		else {
 			*val = 0;
 			hid_sensor_power_state(&gyro_state->common_attributes,
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index beab6d6fd6e1..4bc95f31c730 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
 				HID_USAGE_SENSOR_HUMIDITY,
 				HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
 				humid_st->humidity_attr.report_id,
-				SENSOR_HUB_SYNC);
+				SENSOR_HUB_SYNC,
+				humid_st->humidity_attr.logical_minimum < 0);
 		hid_sensor_power_state(&humid_st->common_attributes, false);
 
 		return IIO_VAL_INT;
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 406caaee9a3c..94f33250ba5a 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
@@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
 		case  CHANNEL_SCAN_INDEX_INTENSITY:
 		case  CHANNEL_SCAN_INDEX_ILLUM:
 			report_id = als_state->als_illum.report_id;
-			address =
-			HID_USAGE_SENSOR_LIGHT_ILLUM;
+			min = als_state->als_illum.logical_minimum;
+			address = HID_USAGE_SENSOR_LIGHT_ILLUM;
 			break;
 		default:
 			report_id = -1;
@@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
 					als_state->common_attributes.hsdev,
 					HID_USAGE_SENSOR_ALS, address,
 					report_id,
-					SENSOR_HUB_SYNC);
+					SENSOR_HUB_SYNC,
+					min < 0);
 			hid_sensor_power_state(&als_state->common_attributes,
 						false);
 		} else {
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 45107f7537b5..cf5a0c242609 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
@@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
 		switch (chan->scan_index) {
 		case  CHANNEL_SCAN_INDEX_PRESENCE:
 			report_id = prox_state->prox_attr.report_id;
-			address =
-			HID_USAGE_SENSOR_HUMAN_PRESENCE;
+			min = prox_state->prox_attr.logical_minimum;
+			address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
 			break;
 		default:
 			report_id = -1;
@@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
 				prox_state->common_attributes.hsdev,
 				HID_USAGE_SENSOR_PROX, address,
 				report_id,
-				SENSOR_HUB_SYNC);
+				SENSOR_HUB_SYNC,
+				min < 0);
 			hid_sensor_power_state(&prox_state->common_attributes,
 						false);
 		} else {
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index d55c4885211a..f3c0d41e5a8c 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
-		report_id =
-			magn_state->magn[chan->address].report_id;
+		report_id = magn_state->magn[chan->address].report_id;
+		min = magn_state->magn[chan->address].logical_minimum;
 		address = magn_3d_addresses[chan->address];
 		if (report_id >= 0)
 			*val = sensor_hub_input_attr_get_raw_value(
 				magn_state->magn_flux_attributes.hsdev,
 				HID_USAGE_SENSOR_COMPASS_3D, address,
 				report_id,
-				SENSOR_HUB_SYNC);
+				SENSOR_HUB_SYNC,
+				min < 0);
 		else {
 			*val = 0;
 			hid_sensor_power_state(
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 1e5451d1ff88..bdc5e4554ee4 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		hid_sensor_power_state(&incl_state->common_attributes, true);
-		report_id =
-			incl_state->incl[chan->scan_index].report_id;
+		report_id = incl_state->incl[chan->scan_index].report_id;
+		min = incl_state->incl[chan->scan_index].logical_minimum;
 		address = incl_3d_addresses[chan->scan_index];
 		if (report_id >= 0)
 			*val = sensor_hub_input_attr_get_raw_value(
 				incl_state->common_attributes.hsdev,
 				HID_USAGE_SENSOR_INCLINOMETER_3D, address,
 				report_id,
-				SENSOR_HUB_SYNC);
+				SENSOR_HUB_SYNC,
+				min < 0);
 		else {
 			hid_sensor_power_state(&incl_state->common_attributes,
 						false);
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 4c437918f1d2..d7b1c00ceb4d 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
 	int report_id = -1;
 	u32 address;
 	int ret_type;
+	s32 min;
 
 	*val = 0;
 	*val2 = 0;
@@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
 		switch (chan->scan_index) {
 		case  CHANNEL_SCAN_INDEX_PRESSURE:
 			report_id = press_state->press_attr.report_id;
-			address =
-			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
+			min = press_state->press_attr.logical_minimum;
+			address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
 			break;
 		default:
 			report_id = -1;
@@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
 				press_state->common_attributes.hsdev,
 				HID_USAGE_SENSOR_PRESSURE, address,
 				report_id,
-				SENSOR_HUB_SYNC);
+				SENSOR_HUB_SYNC,
+				min < 0);
 			hid_sensor_power_state(&press_state->common_attributes,
 						false);
 		} else {
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index beaf6fd3e337..b592fc4f007e 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
 			HID_USAGE_SENSOR_TEMPERATURE,
 			HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
 			temp_st->temperature_attr.report_id,
-			SENSOR_HUB_SYNC);
+			SENSOR_HUB_SYNC,
+			temp_st->temperature_attr.logical_minimum < 0);
 		hid_sensor_power_state(
 				&temp_st->common_attributes,
 				false);
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 2751dba850c6..3e1abb455472 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	/* get a report with all values through requesting one value */
 	sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
 			HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
-			time_state->info[0].report_id, SENSOR_HUB_SYNC);
+			time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
 	/* wait for all values (event) */
 	ret = wait_for_completion_killable_timeout(
 			&time_state->comp_last_time, HZ*6);
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index 331dc377c275..dc12f5c4b076 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 * @attr_usage_id:	Attribute usage id as per spec
 * @report_id:	Report id to look for
 * @flag:      Synchronous or asynchronous read
+* @is_signed:   If true then fields < 32 bits will be sign-extended
 *
 * Issues a synchronous or asynchronous read request for an input attribute.
 * Returns data upto 32 bits.
@@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
  					u32 usage_id,
  					u32 attr_usage_id, u32 report_id,
- 					enum sensor_hub_read_flags flag
+					enum sensor_hub_read_flags flag,
+					bool is_signed
 );
 
 /**
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-10-31 14:20 [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers Hans de Goede
@ 2018-10-31 14:21 ` Hans de Goede
  2018-11-03 12:26 ` Jonathan Cameron
  2018-11-13 13:09 ` Bastien Nocera
  2 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2018-10-31 14:21 UTC (permalink / raw)
  To: Srinivas Pandruvada, Jonathan Cameron, Jiri Kosina,
	Benjamin Tissoires
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio, linux-input

Hi,

On 31-10-18 15:20, Hans de Goede wrote:
> Before this commit sensor_hub_input_attr_get_raw_value() failed to take
> the signedness of 16 and 8 bit values into account, returning e.g.
> 65436 instead of -100 for the z-axis reading of an accelerometer.
> 
> This commit adds a new is_signed parameter to the function and makes all
> callers pass the appropriate value for this.
> 
> While at it, this commit also fixes up some neighboring lines where
> statements were needlessly split over 2 lines to improve readability.
> 
> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> Changes in v2:
> -Adjust the kernel doc for the new is_signed parameter to
>   sensor_hub_input_attr_get_raw_value()
> -Add Srinivas' Acked-by

This second copy of this patch is a resend with the HID maintainers
added, which I accidentally forgot in the first posting of v2.

This is still v2 with no changes compared to my first submission of v2.

Regards,

Hans



> ---
>   drivers/hid/hid-sensor-custom.c                  |  2 +-
>   drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++---
>   drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
>   drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
>   drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
>   drivers/iio/light/hid-sensor-als.c               |  8 +++++---
>   drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
>   drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
>   drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
>   drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
>   drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
>   drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
>   include/linux/hid-sensor-hub.h                   |  4 +++-
>   13 files changed, 52 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
> index e8a114157f87..bb012bc032e0 100644
> --- a/drivers/hid/hid-sensor-custom.c
> +++ b/drivers/hid/hid-sensor-custom.c
> @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
>   						sensor_inst->hsdev,
>   						sensor_inst->hsdev->usage,
>   						usage, report_id,
> -						SENSOR_HUB_SYNC);
> +						SENSOR_HUB_SYNC, false);
>   	} else if (!strncmp(name, "units", strlen("units")))
>   		value = sensor_inst->fields[field_index].attribute.units;
>   	else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> index 2b63487057c2..4256fdc5cd6d 100644
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c
> @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
>   int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>   					u32 usage_id,
>   					u32 attr_usage_id, u32 report_id,
> -					enum sensor_hub_read_flags flag)
> +					enum sensor_hub_read_flags flag,
> +					bool is_signed)
>   {
>   	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
>   	unsigned long flags;
> @@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>   						&hsdev->pending.ready, HZ*5);
>   		switch (hsdev->pending.raw_size) {
>   		case 1:
> -			ret_val = *(u8 *)hsdev->pending.raw_data;
> +			if (is_signed)
> +				ret_val = *(s8 *)hsdev->pending.raw_data;
> +			else
> +				ret_val = *(u8 *)hsdev->pending.raw_data;
>   			break;
>   		case 2:
> -			ret_val = *(u16 *)hsdev->pending.raw_data;
> +			if (is_signed)
> +				ret_val = *(s16 *)hsdev->pending.raw_data;
> +			else
> +				ret_val = *(u16 *)hsdev->pending.raw_data;
>   			break;
>   		case 4:
>   			ret_val = *(u32 *)hsdev->pending.raw_data;
> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> index 41d97faf5013..38ff374a3ca4 100644
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   	struct hid_sensor_hub_device *hsdev =
>   					accel_state->common_attributes.hsdev;
>   
> @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
>   	case IIO_CHAN_INFO_RAW:
>   		hid_sensor_power_state(&accel_state->common_attributes, true);
>   		report_id = accel_state->accel[chan->scan_index].report_id;
> +		min = accel_state->accel[chan->scan_index].logical_minimum;
>   		address = accel_3d_addresses[chan->scan_index];
>   		if (report_id >= 0)
>   			*val = sensor_hub_input_attr_get_raw_value(
>   					accel_state->common_attributes.hsdev,
>   					hsdev->usage, address, report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>   		else {
>   			*val = 0;
>   			hid_sensor_power_state(&accel_state->common_attributes,
> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> index 36941e69f959..88e857c4baf4 100644
> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
> @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
>   	case IIO_CHAN_INFO_RAW:
>   		hid_sensor_power_state(&gyro_state->common_attributes, true);
>   		report_id = gyro_state->gyro[chan->scan_index].report_id;
> +		min = gyro_state->gyro[chan->scan_index].logical_minimum;
>   		address = gyro_3d_addresses[chan->scan_index];
>   		if (report_id >= 0)
>   			*val = sensor_hub_input_attr_get_raw_value(
>   					gyro_state->common_attributes.hsdev,
>   					HID_USAGE_SENSOR_GYRO_3D, address,
>   					report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>   		else {
>   			*val = 0;
>   			hid_sensor_power_state(&gyro_state->common_attributes,
> diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
> index beab6d6fd6e1..4bc95f31c730 100644
> --- a/drivers/iio/humidity/hid-sensor-humidity.c
> +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
>   				HID_USAGE_SENSOR_HUMIDITY,
>   				HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
>   				humid_st->humidity_attr.report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				humid_st->humidity_attr.logical_minimum < 0);
>   		hid_sensor_power_state(&humid_st->common_attributes, false);
>   
>   		return IIO_VAL_INT;
> diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
> index 406caaee9a3c..94f33250ba5a 100644
> --- a/drivers/iio/light/hid-sensor-als.c
> +++ b/drivers/iio/light/hid-sensor-als.c
> @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
> @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
>   		case  CHANNEL_SCAN_INDEX_INTENSITY:
>   		case  CHANNEL_SCAN_INDEX_ILLUM:
>   			report_id = als_state->als_illum.report_id;
> -			address =
> -			HID_USAGE_SENSOR_LIGHT_ILLUM;
> +			min = als_state->als_illum.logical_minimum;
> +			address = HID_USAGE_SENSOR_LIGHT_ILLUM;
>   			break;
>   		default:
>   			report_id = -1;
> @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
>   					als_state->common_attributes.hsdev,
>   					HID_USAGE_SENSOR_ALS, address,
>   					report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>   			hid_sensor_power_state(&als_state->common_attributes,
>   						false);
>   		} else {
> diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> index 45107f7537b5..cf5a0c242609 100644
> --- a/drivers/iio/light/hid-sensor-prox.c
> +++ b/drivers/iio/light/hid-sensor-prox.c
> @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
> @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>   		switch (chan->scan_index) {
>   		case  CHANNEL_SCAN_INDEX_PRESENCE:
>   			report_id = prox_state->prox_attr.report_id;
> -			address =
> -			HID_USAGE_SENSOR_HUMAN_PRESENCE;
> +			min = prox_state->prox_attr.logical_minimum;
> +			address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
>   			break;
>   		default:
>   			report_id = -1;
> @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>   				prox_state->common_attributes.hsdev,
>   				HID_USAGE_SENSOR_PROX, address,
>   				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>   			hid_sensor_power_state(&prox_state->common_attributes,
>   						false);
>   		} else {
> diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> index d55c4885211a..f3c0d41e5a8c 100644
> --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
>   	switch (mask) {
>   	case IIO_CHAN_INFO_RAW:
>   		hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
> -		report_id =
> -			magn_state->magn[chan->address].report_id;
> +		report_id = magn_state->magn[chan->address].report_id;
> +		min = magn_state->magn[chan->address].logical_minimum;
>   		address = magn_3d_addresses[chan->address];
>   		if (report_id >= 0)
>   			*val = sensor_hub_input_attr_get_raw_value(
>   				magn_state->magn_flux_attributes.hsdev,
>   				HID_USAGE_SENSOR_COMPASS_3D, address,
>   				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>   		else {
>   			*val = 0;
>   			hid_sensor_power_state(
> diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> index 1e5451d1ff88..bdc5e4554ee4 100644
> --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
>   	switch (mask) {
>   	case IIO_CHAN_INFO_RAW:
>   		hid_sensor_power_state(&incl_state->common_attributes, true);
> -		report_id =
> -			incl_state->incl[chan->scan_index].report_id;
> +		report_id = incl_state->incl[chan->scan_index].report_id;
> +		min = incl_state->incl[chan->scan_index].logical_minimum;
>   		address = incl_3d_addresses[chan->scan_index];
>   		if (report_id >= 0)
>   			*val = sensor_hub_input_attr_get_raw_value(
>   				incl_state->common_attributes.hsdev,
>   				HID_USAGE_SENSOR_INCLINOMETER_3D, address,
>   				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>   		else {
>   			hid_sensor_power_state(&incl_state->common_attributes,
>   						false);
> diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> index 4c437918f1d2..d7b1c00ceb4d 100644
> --- a/drivers/iio/pressure/hid-sensor-press.c
> +++ b/drivers/iio/pressure/hid-sensor-press.c
> @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
>   	int report_id = -1;
>   	u32 address;
>   	int ret_type;
> +	s32 min;
>   
>   	*val = 0;
>   	*val2 = 0;
> @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
>   		switch (chan->scan_index) {
>   		case  CHANNEL_SCAN_INDEX_PRESSURE:
>   			report_id = press_state->press_attr.report_id;
> -			address =
> -			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> +			min = press_state->press_attr.logical_minimum;
> +			address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
>   			break;
>   		default:
>   			report_id = -1;
> @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
>   				press_state->common_attributes.hsdev,
>   				HID_USAGE_SENSOR_PRESSURE, address,
>   				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>   			hid_sensor_power_state(&press_state->common_attributes,
>   						false);
>   		} else {
> diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> index beaf6fd3e337..b592fc4f007e 100644
> --- a/drivers/iio/temperature/hid-sensor-temperature.c
> +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
>   			HID_USAGE_SENSOR_TEMPERATURE,
>   			HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
>   			temp_st->temperature_attr.report_id,
> -			SENSOR_HUB_SYNC);
> +			SENSOR_HUB_SYNC,
> +			temp_st->temperature_attr.logical_minimum < 0);
>   		hid_sensor_power_state(
>   				&temp_st->common_attributes,
>   				false);
> diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
> index 2751dba850c6..3e1abb455472 100644
> --- a/drivers/rtc/rtc-hid-sensor-time.c
> +++ b/drivers/rtc/rtc-hid-sensor-time.c
> @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
>   	/* get a report with all values through requesting one value */
>   	sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
>   			HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
> -			time_state->info[0].report_id, SENSOR_HUB_SYNC);
> +			time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
>   	/* wait for all values (event) */
>   	ret = wait_for_completion_killable_timeout(
>   			&time_state->comp_last_time, HZ*6);
> diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
> index 331dc377c275..dc12f5c4b076 100644
> --- a/include/linux/hid-sensor-hub.h
> +++ b/include/linux/hid-sensor-hub.h
> @@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
>   * @attr_usage_id:	Attribute usage id as per spec
>   * @report_id:	Report id to look for
>   * @flag:      Synchronous or asynchronous read
> +* @is_signed:   If true then fields < 32 bits will be sign-extended
>   *
>   * Issues a synchronous or asynchronous read request for an input attribute.
>   * Returns data upto 32 bits.
> @@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
>   int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>    					u32 usage_id,
>    					u32 attr_usage_id, u32 report_id,
> - 					enum sensor_hub_read_flags flag
> +					enum sensor_hub_read_flags flag,
> +					bool is_signed
>   );
>   
>   /**
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-10-31 14:20 [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers Hans de Goede
  2018-10-31 14:21 ` Hans de Goede
@ 2018-11-03 12:26 ` Jonathan Cameron
  2018-11-03 15:53   ` Srinivas Pandruvada
  2018-11-15  8:20   ` Benjamin Tissoires
  2018-11-13 13:09 ` Bastien Nocera
  2 siblings, 2 replies; 8+ messages in thread
From: Jonathan Cameron @ 2018-11-03 12:26 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio, linux-input

On Wed, 31 Oct 2018 15:20:05 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Before this commit sensor_hub_input_attr_get_raw_value() failed to take
> the signedness of 16 and 8 bit values into account, returning e.g.
> 65436 instead of -100 for the z-axis reading of an accelerometer.
> 
> This commit adds a new is_signed parameter to the function and makes all
> callers pass the appropriate value for this.
> 
> While at it, this commit also fixes up some neighboring lines where
> statements were needlessly split over 2 lines to improve readability.
> 
> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Yikes.  Not sure how this was missed for so long.

I'll want the hid maintainers ack for this but probably makes sense
to take it through IIO.

Is this a for all time thing or should we have an explict Fixes
tag in place?

I do wonder if we have userspace code working around this which
is going to get confused, but fingers crossed that's not the case.

Definitely stable material I think.

Jonathan

> ---
> Changes in v2:
> -Adjust the kernel doc for the new is_signed parameter to
>  sensor_hub_input_attr_get_raw_value()
> -Add Srinivas' Acked-by
> ---
>  drivers/hid/hid-sensor-custom.c                  |  2 +-
>  drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++---
>  drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
>  drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
>  drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
>  drivers/iio/light/hid-sensor-als.c               |  8 +++++---
>  drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
>  drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
>  drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
>  drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
>  drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
>  drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
>  include/linux/hid-sensor-hub.h                   |  4 +++-
>  13 files changed, 52 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
> index e8a114157f87..bb012bc032e0 100644
> --- a/drivers/hid/hid-sensor-custom.c
> +++ b/drivers/hid/hid-sensor-custom.c
> @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
>  						sensor_inst->hsdev,
>  						sensor_inst->hsdev->usage,
>  						usage, report_id,
> -						SENSOR_HUB_SYNC);
> +						SENSOR_HUB_SYNC, false);
>  	} else if (!strncmp(name, "units", strlen("units")))
>  		value = sensor_inst->fields[field_index].attribute.units;
>  	else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> index 2b63487057c2..4256fdc5cd6d 100644
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c
> @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
>  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>  					u32 usage_id,
>  					u32 attr_usage_id, u32 report_id,
> -					enum sensor_hub_read_flags flag)
> +					enum sensor_hub_read_flags flag,
> +					bool is_signed)
>  {
>  	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
>  	unsigned long flags;
> @@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>  						&hsdev->pending.ready, HZ*5);
>  		switch (hsdev->pending.raw_size) {
>  		case 1:
> -			ret_val = *(u8 *)hsdev->pending.raw_data;
> +			if (is_signed)
> +				ret_val = *(s8 *)hsdev->pending.raw_data;
> +			else
> +				ret_val = *(u8 *)hsdev->pending.raw_data;
>  			break;
>  		case 2:
> -			ret_val = *(u16 *)hsdev->pending.raw_data;
> +			if (is_signed)
> +				ret_val = *(s16 *)hsdev->pending.raw_data;
> +			else
> +				ret_val = *(u16 *)hsdev->pending.raw_data;
>  			break;
>  		case 4:
>  			ret_val = *(u32 *)hsdev->pending.raw_data;
> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> index 41d97faf5013..38ff374a3ca4 100644
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  	struct hid_sensor_hub_device *hsdev =
>  					accel_state->common_attributes.hsdev;
>  
> @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
>  	case IIO_CHAN_INFO_RAW:
>  		hid_sensor_power_state(&accel_state->common_attributes, true);
>  		report_id = accel_state->accel[chan->scan_index].report_id;
> +		min = accel_state->accel[chan->scan_index].logical_minimum;
>  		address = accel_3d_addresses[chan->scan_index];
>  		if (report_id >= 0)
>  			*val = sensor_hub_input_attr_get_raw_value(
>  					accel_state->common_attributes.hsdev,
>  					hsdev->usage, address, report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>  		else {
>  			*val = 0;
>  			hid_sensor_power_state(&accel_state->common_attributes,
> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> index 36941e69f959..88e857c4baf4 100644
> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
> @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
>  	case IIO_CHAN_INFO_RAW:
>  		hid_sensor_power_state(&gyro_state->common_attributes, true);
>  		report_id = gyro_state->gyro[chan->scan_index].report_id;
> +		min = gyro_state->gyro[chan->scan_index].logical_minimum;
>  		address = gyro_3d_addresses[chan->scan_index];
>  		if (report_id >= 0)
>  			*val = sensor_hub_input_attr_get_raw_value(
>  					gyro_state->common_attributes.hsdev,
>  					HID_USAGE_SENSOR_GYRO_3D, address,
>  					report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>  		else {
>  			*val = 0;
>  			hid_sensor_power_state(&gyro_state->common_attributes,
> diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
> index beab6d6fd6e1..4bc95f31c730 100644
> --- a/drivers/iio/humidity/hid-sensor-humidity.c
> +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
>  				HID_USAGE_SENSOR_HUMIDITY,
>  				HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
>  				humid_st->humidity_attr.report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				humid_st->humidity_attr.logical_minimum < 0);
>  		hid_sensor_power_state(&humid_st->common_attributes, false);
>  
>  		return IIO_VAL_INT;
> diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
> index 406caaee9a3c..94f33250ba5a 100644
> --- a/drivers/iio/light/hid-sensor-als.c
> +++ b/drivers/iio/light/hid-sensor-als.c
> @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
> @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
>  		case  CHANNEL_SCAN_INDEX_INTENSITY:
>  		case  CHANNEL_SCAN_INDEX_ILLUM:
>  			report_id = als_state->als_illum.report_id;
> -			address =
> -			HID_USAGE_SENSOR_LIGHT_ILLUM;
> +			min = als_state->als_illum.logical_minimum;
> +			address = HID_USAGE_SENSOR_LIGHT_ILLUM;
>  			break;
>  		default:
>  			report_id = -1;
> @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
>  					als_state->common_attributes.hsdev,
>  					HID_USAGE_SENSOR_ALS, address,
>  					report_id,
> -					SENSOR_HUB_SYNC);
> +					SENSOR_HUB_SYNC,
> +					min < 0);
>  			hid_sensor_power_state(&als_state->common_attributes,
>  						false);
>  		} else {
> diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> index 45107f7537b5..cf5a0c242609 100644
> --- a/drivers/iio/light/hid-sensor-prox.c
> +++ b/drivers/iio/light/hid-sensor-prox.c
> @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
> @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>  		switch (chan->scan_index) {
>  		case  CHANNEL_SCAN_INDEX_PRESENCE:
>  			report_id = prox_state->prox_attr.report_id;
> -			address =
> -			HID_USAGE_SENSOR_HUMAN_PRESENCE;
> +			min = prox_state->prox_attr.logical_minimum;
> +			address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
>  			break;
>  		default:
>  			report_id = -1;
> @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
>  				prox_state->common_attributes.hsdev,
>  				HID_USAGE_SENSOR_PROX, address,
>  				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>  			hid_sensor_power_state(&prox_state->common_attributes,
>  						false);
>  		} else {
> diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> index d55c4885211a..f3c0d41e5a8c 100644
> --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
>  		hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
> -		report_id =
> -			magn_state->magn[chan->address].report_id;
> +		report_id = magn_state->magn[chan->address].report_id;
> +		min = magn_state->magn[chan->address].logical_minimum;
>  		address = magn_3d_addresses[chan->address];
>  		if (report_id >= 0)
>  			*val = sensor_hub_input_attr_get_raw_value(
>  				magn_state->magn_flux_attributes.hsdev,
>  				HID_USAGE_SENSOR_COMPASS_3D, address,
>  				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>  		else {
>  			*val = 0;
>  			hid_sensor_power_state(
> diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> index 1e5451d1ff88..bdc5e4554ee4 100644
> --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
>  		hid_sensor_power_state(&incl_state->common_attributes, true);
> -		report_id =
> -			incl_state->incl[chan->scan_index].report_id;
> +		report_id = incl_state->incl[chan->scan_index].report_id;
> +		min = incl_state->incl[chan->scan_index].logical_minimum;
>  		address = incl_3d_addresses[chan->scan_index];
>  		if (report_id >= 0)
>  			*val = sensor_hub_input_attr_get_raw_value(
>  				incl_state->common_attributes.hsdev,
>  				HID_USAGE_SENSOR_INCLINOMETER_3D, address,
>  				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>  		else {
>  			hid_sensor_power_state(&incl_state->common_attributes,
>  						false);
> diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> index 4c437918f1d2..d7b1c00ceb4d 100644
> --- a/drivers/iio/pressure/hid-sensor-press.c
> +++ b/drivers/iio/pressure/hid-sensor-press.c
> @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
>  	int report_id = -1;
>  	u32 address;
>  	int ret_type;
> +	s32 min;
>  
>  	*val = 0;
>  	*val2 = 0;
> @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
>  		switch (chan->scan_index) {
>  		case  CHANNEL_SCAN_INDEX_PRESSURE:
>  			report_id = press_state->press_attr.report_id;
> -			address =
> -			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> +			min = press_state->press_attr.logical_minimum;
> +			address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
>  			break;
>  		default:
>  			report_id = -1;
> @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
>  				press_state->common_attributes.hsdev,
>  				HID_USAGE_SENSOR_PRESSURE, address,
>  				report_id,
> -				SENSOR_HUB_SYNC);
> +				SENSOR_HUB_SYNC,
> +				min < 0);
>  			hid_sensor_power_state(&press_state->common_attributes,
>  						false);
>  		} else {
> diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> index beaf6fd3e337..b592fc4f007e 100644
> --- a/drivers/iio/temperature/hid-sensor-temperature.c
> +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
>  			HID_USAGE_SENSOR_TEMPERATURE,
>  			HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
>  			temp_st->temperature_attr.report_id,
> -			SENSOR_HUB_SYNC);
> +			SENSOR_HUB_SYNC,
> +			temp_st->temperature_attr.logical_minimum < 0);
>  		hid_sensor_power_state(
>  				&temp_st->common_attributes,
>  				false);
> diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
> index 2751dba850c6..3e1abb455472 100644
> --- a/drivers/rtc/rtc-hid-sensor-time.c
> +++ b/drivers/rtc/rtc-hid-sensor-time.c
> @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
>  	/* get a report with all values through requesting one value */
>  	sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
>  			HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
> -			time_state->info[0].report_id, SENSOR_HUB_SYNC);
> +			time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
>  	/* wait for all values (event) */
>  	ret = wait_for_completion_killable_timeout(
>  			&time_state->comp_last_time, HZ*6);
> diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
> index 331dc377c275..dc12f5c4b076 100644
> --- a/include/linux/hid-sensor-hub.h
> +++ b/include/linux/hid-sensor-hub.h
> @@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
>  * @attr_usage_id:	Attribute usage id as per spec
>  * @report_id:	Report id to look for
>  * @flag:      Synchronous or asynchronous read
> +* @is_signed:   If true then fields < 32 bits will be sign-extended
>  *
>  * Issues a synchronous or asynchronous read request for an input attribute.
>  * Returns data upto 32 bits.
> @@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
>  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
>   					u32 usage_id,
>   					u32 attr_usage_id, u32 report_id,
> - 					enum sensor_hub_read_flags flag
> +					enum sensor_hub_read_flags flag,
> +					bool is_signed
>  );
>  
>  /**

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-11-03 12:26 ` Jonathan Cameron
@ 2018-11-03 15:53   ` Srinivas Pandruvada
  2018-11-15  8:20   ` Benjamin Tissoires
  1 sibling, 0 replies; 8+ messages in thread
From: Srinivas Pandruvada @ 2018-11-03 15:53 UTC (permalink / raw)
  To: Jonathan Cameron, Hans de Goede
  Cc: Jiri Kosina, Benjamin Tissoires, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, linux-iio,
	linux-input

On Sat, 2018-11-03 at 12:26 +0000, Jonathan Cameron wrote:
> On Wed, 31 Oct 2018 15:20:05 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
> 
> > Before this commit sensor_hub_input_attr_get_raw_value() failed to
> > take
> > the signedness of 16 and 8 bit values into account, returning e.g.
> > 65436 instead of -100 for the z-axis reading of an accelerometer.
> > 
> > This commit adds a new is_signed parameter to the function and
> > makes all
> > callers pass the appropriate value for this.
> > 
> > While at it, this commit also fixes up some neighboring lines where
> > statements were needlessly split over 2 lines to improve
> > readability.
> > 
> > Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> > Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> 
> Yikes.  Not sure how this was missed for so long.
This is issue only when not 4 bytes, which is the case in most cases.
The reliance on logical minimum was always risky before. 

> 
> I'll want the hid maintainers ack for this but probably makes sense
> to take it through IIO.
> 
> Is this a for all time thing or should we have an explict Fixes
> tag in place?
I think explicit fix is fine as the user space is using buffered mode
where they know size and sign.

> 
> I do wonder if we have userspace code working around this which
> is going to get confused, but fingers crossed that's not the case.
> 
> Definitely stable material I think.
Yes.

Thanks,
Srinivas
> 
> Jonathan
> 
> > ---
> > Changes in v2:
> > -Adjust the kernel doc for the new is_signed parameter to
> >  sensor_hub_input_attr_get_raw_value()
> > -Add Srinivas' Acked-by
> > ---
> >  drivers/hid/hid-sensor-custom.c                  |  2 +-
> >  drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++
> > ---
> >  drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
> >  drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
> >  drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
> >  drivers/iio/light/hid-sensor-als.c               |  8 +++++---
> >  drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
> >  drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
> >  drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
> >  drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
> >  drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
> >  drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
> >  include/linux/hid-sensor-hub.h                   |  4 +++-
> >  13 files changed, 52 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-
> > sensor-custom.c
> > index e8a114157f87..bb012bc032e0 100644
> > --- a/drivers/hid/hid-sensor-custom.c
> > +++ b/drivers/hid/hid-sensor-custom.c
> > @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev,
> > struct device_attribute *attr,
> >  						sensor_inst->hsdev,
> >  						sensor_inst->hsdev-
> > >usage,
> >  						usage, report_id,
> > -						SENSOR_HUB_SYNC);
> > +						SENSOR_HUB_SYNC,
> > false);
> >  	} else if (!strncmp(name, "units", strlen("units")))
> >  		value = sensor_inst-
> > >fields[field_index].attribute.units;
> >  	else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
> > diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-
> > hub.c
> > index 2b63487057c2..4256fdc5cd6d 100644
> > --- a/drivers/hid/hid-sensor-hub.c
> > +++ b/drivers/hid/hid-sensor-hub.c
> > @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
> >  int sensor_hub_input_attr_get_raw_value(struct
> > hid_sensor_hub_device *hsdev,
> >  					u32 usage_id,
> >  					u32 attr_usage_id, u32
> > report_id,
> > -					enum sensor_hub_read_flags
> > flag)
> > +					enum sensor_hub_read_flags
> > flag,
> > +					bool is_signed)
> >  {
> >  	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
> >  	unsigned long flags;
> > @@ -331,10 +332,16 @@ int
> > sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device
> > *hsdev,
> >  						&hsdev->pending.ready,
> > HZ*5);
> >  		switch (hsdev->pending.raw_size) {
> >  		case 1:
> > -			ret_val = *(u8 *)hsdev->pending.raw_data;
> > +			if (is_signed)
> > +				ret_val = *(s8 *)hsdev-
> > >pending.raw_data;
> > +			else
> > +				ret_val = *(u8 *)hsdev-
> > >pending.raw_data;
> >  			break;
> >  		case 2:
> > -			ret_val = *(u16 *)hsdev->pending.raw_data;
> > +			if (is_signed)
> > +				ret_val = *(s16 *)hsdev-
> > >pending.raw_data;
> > +			else
> > +				ret_val = *(u16 *)hsdev-
> > >pending.raw_data;
> >  			break;
> >  		case 4:
> >  			ret_val = *(u32 *)hsdev->pending.raw_data;
> > diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c
> > b/drivers/iio/accel/hid-sensor-accel-3d.c
> > index 41d97faf5013..38ff374a3ca4 100644
> > --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> > +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> > @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  	struct hid_sensor_hub_device *hsdev =
> >  					accel_state-
> > >common_attributes.hsdev;
> >  
> > @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	case IIO_CHAN_INFO_RAW:
> >  		hid_sensor_power_state(&accel_state->common_attributes, 
> > true);
> >  		report_id = accel_state->accel[chan-
> > >scan_index].report_id;
> > +		min = accel_state->accel[chan-
> > >scan_index].logical_minimum;
> >  		address = accel_3d_addresses[chan->scan_index];
> >  		if (report_id >= 0)
> >  			*val = sensor_hub_input_attr_get_raw_value(
> >  					accel_state-
> > >common_attributes.hsdev,
> >  					hsdev->usage, address,
> > report_id,
> > -					SENSOR_HUB_SYNC);
> > +					SENSOR_HUB_SYNC,
> > +					min < 0);
> >  		else {
> >  			*val = 0;
> >  			hid_sensor_power_state(&accel_state-
> > >common_attributes,
> > diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > index 36941e69f959..88e857c4baf4 100644
> > --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> > @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	case IIO_CHAN_INFO_RAW:
> >  		hid_sensor_power_state(&gyro_state->common_attributes,
> > true);
> >  		report_id = gyro_state->gyro[chan-
> > >scan_index].report_id;
> > +		min = gyro_state->gyro[chan-
> > >scan_index].logical_minimum;
> >  		address = gyro_3d_addresses[chan->scan_index];
> >  		if (report_id >= 0)
> >  			*val = sensor_hub_input_attr_get_raw_value(
> >  					gyro_state-
> > >common_attributes.hsdev,
> >  					HID_USAGE_SENSOR_GYRO_3D,
> > address,
> >  					report_id,
> > -					SENSOR_HUB_SYNC);
> > +					SENSOR_HUB_SYNC,
> > +					min < 0);
> >  		else {
> >  			*val = 0;
> >  			hid_sensor_power_state(&gyro_state-
> > >common_attributes,
> > diff --git a/drivers/iio/humidity/hid-sensor-humidity.c
> > b/drivers/iio/humidity/hid-sensor-humidity.c
> > index beab6d6fd6e1..4bc95f31c730 100644
> > --- a/drivers/iio/humidity/hid-sensor-humidity.c
> > +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> > @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev
> > *indio_dev,
> >  				HID_USAGE_SENSOR_HUMIDITY,
> >  				HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
> >  				humid_st->humidity_attr.report_id,
> > -				SENSOR_HUB_SYNC);
> > +				SENSOR_HUB_SYNC,
> > +				humid_st->humidity_attr.logical_minimum 
> > < 0);
> >  		hid_sensor_power_state(&humid_st->common_attributes,
> > false);
> >  
> >  		return IIO_VAL_INT;
> > diff --git a/drivers/iio/light/hid-sensor-als.c
> > b/drivers/iio/light/hid-sensor-als.c
> > index 406caaee9a3c..94f33250ba5a 100644
> > --- a/drivers/iio/light/hid-sensor-als.c
> > +++ b/drivers/iio/light/hid-sensor-als.c
> > @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> > @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev
> > *indio_dev,
> >  		case  CHANNEL_SCAN_INDEX_INTENSITY:
> >  		case  CHANNEL_SCAN_INDEX_ILLUM:
> >  			report_id = als_state->als_illum.report_id;
> > -			address =
> > -			HID_USAGE_SENSOR_LIGHT_ILLUM;
> > +			min = als_state->als_illum.logical_minimum;
> > +			address = HID_USAGE_SENSOR_LIGHT_ILLUM;
> >  			break;
> >  		default:
> >  			report_id = -1;
> > @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev
> > *indio_dev,
> >  					als_state-
> > >common_attributes.hsdev,
> >  					HID_USAGE_SENSOR_ALS, address,
> >  					report_id,
> > -					SENSOR_HUB_SYNC);
> > +					SENSOR_HUB_SYNC,
> > +					min < 0);
> >  			hid_sensor_power_state(&als_state-
> > >common_attributes,
> >  						false);
> >  		} else {
> > diff --git a/drivers/iio/light/hid-sensor-prox.c
> > b/drivers/iio/light/hid-sensor-prox.c
> > index 45107f7537b5..cf5a0c242609 100644
> > --- a/drivers/iio/light/hid-sensor-prox.c
> > +++ b/drivers/iio/light/hid-sensor-prox.c
> > @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> > @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev
> > *indio_dev,
> >  		switch (chan->scan_index) {
> >  		case  CHANNEL_SCAN_INDEX_PRESENCE:
> >  			report_id = prox_state->prox_attr.report_id;
> > -			address =
> > -			HID_USAGE_SENSOR_HUMAN_PRESENCE;
> > +			min = prox_state->prox_attr.logical_minimum;
> > +			address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
> >  			break;
> >  		default:
> >  			report_id = -1;
> > @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev
> > *indio_dev,
> >  				prox_state->common_attributes.hsdev,
> >  				HID_USAGE_SENSOR_PROX, address,
> >  				report_id,
> > -				SENSOR_HUB_SYNC);
> > +				SENSOR_HUB_SYNC,
> > +				min < 0);
> >  			hid_sensor_power_state(&prox_state-
> > >common_attributes,
> >  						false);
> >  		} else {
> > diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > index d55c4885211a..f3c0d41e5a8c 100644
> > --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> >  	switch (mask) {
> >  	case IIO_CHAN_INFO_RAW:
> >  		hid_sensor_power_state(&magn_state-
> > >magn_flux_attributes, true);
> > -		report_id =
> > -			magn_state->magn[chan->address].report_id;
> > +		report_id = magn_state->magn[chan->address].report_id;
> > +		min = magn_state->magn[chan->address].logical_minimum;
> >  		address = magn_3d_addresses[chan->address];
> >  		if (report_id >= 0)
> >  			*val = sensor_hub_input_attr_get_raw_value(
> >  				magn_state->magn_flux_attributes.hsdev,
> >  				HID_USAGE_SENSOR_COMPASS_3D, address,
> >  				report_id,
> > -				SENSOR_HUB_SYNC);
> > +				SENSOR_HUB_SYNC,
> > +				min < 0);
> >  		else {
> >  			*val = 0;
> >  			hid_sensor_power_state(
> > diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c
> > b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > index 1e5451d1ff88..bdc5e4554ee4 100644
> > --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> > +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> >  	switch (mask) {
> >  	case IIO_CHAN_INFO_RAW:
> >  		hid_sensor_power_state(&incl_state->common_attributes,
> > true);
> > -		report_id =
> > -			incl_state->incl[chan->scan_index].report_id;
> > +		report_id = incl_state->incl[chan-
> > >scan_index].report_id;
> > +		min = incl_state->incl[chan-
> > >scan_index].logical_minimum;
> >  		address = incl_3d_addresses[chan->scan_index];
> >  		if (report_id >= 0)
> >  			*val = sensor_hub_input_attr_get_raw_value(
> >  				incl_state->common_attributes.hsdev,
> >  				HID_USAGE_SENSOR_INCLINOMETER_3D,
> > address,
> >  				report_id,
> > -				SENSOR_HUB_SYNC);
> > +				SENSOR_HUB_SYNC,
> > +				min < 0);
> >  		else {
> >  			hid_sensor_power_state(&incl_state-
> > >common_attributes,
> >  						false);
> > diff --git a/drivers/iio/pressure/hid-sensor-press.c
> > b/drivers/iio/pressure/hid-sensor-press.c
> > index 4c437918f1d2..d7b1c00ceb4d 100644
> > --- a/drivers/iio/pressure/hid-sensor-press.c
> > +++ b/drivers/iio/pressure/hid-sensor-press.c
> > @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev
> > *indio_dev,
> >  	int report_id = -1;
> >  	u32 address;
> >  	int ret_type;
> > +	s32 min;
> >  
> >  	*val = 0;
> >  	*val2 = 0;
> > @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev
> > *indio_dev,
> >  		switch (chan->scan_index) {
> >  		case  CHANNEL_SCAN_INDEX_PRESSURE:
> >  			report_id = press_state->press_attr.report_id;
> > -			address =
> > -			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> > +			min = press_state->press_attr.logical_minimum;
> > +			address =
> > HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> >  			break;
> >  		default:
> >  			report_id = -1;
> > @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev
> > *indio_dev,
> >  				press_state->common_attributes.hsdev,
> >  				HID_USAGE_SENSOR_PRESSURE, address,
> >  				report_id,
> > -				SENSOR_HUB_SYNC);
> > +				SENSOR_HUB_SYNC,
> > +				min < 0);
> >  			hid_sensor_power_state(&press_state-
> > >common_attributes,
> >  						false);
> >  		} else {
> > diff --git a/drivers/iio/temperature/hid-sensor-temperature.c
> > b/drivers/iio/temperature/hid-sensor-temperature.c
> > index beaf6fd3e337..b592fc4f007e 100644
> > --- a/drivers/iio/temperature/hid-sensor-temperature.c
> > +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> > @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev
> > *indio_dev,
> >  			HID_USAGE_SENSOR_TEMPERATURE,
> >  			HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE
> > ,
> >  			temp_st->temperature_attr.report_id,
> > -			SENSOR_HUB_SYNC);
> > +			SENSOR_HUB_SYNC,
> > +			temp_st->temperature_attr.logical_minimum < 0);
> >  		hid_sensor_power_state(
> >  				&temp_st->common_attributes,
> >  				false);
> > diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-
> > hid-sensor-time.c
> > index 2751dba850c6..3e1abb455472 100644
> > --- a/drivers/rtc/rtc-hid-sensor-time.c
> > +++ b/drivers/rtc/rtc-hid-sensor-time.c
> > @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device
> > *dev, struct rtc_time *tm)
> >  	/* get a report with all values through requesting one value */
> >  	sensor_hub_input_attr_get_raw_value(time_state-
> > >common_attributes.hsdev,
> >  			HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
> > -			time_state->info[0].report_id,
> > SENSOR_HUB_SYNC);
> > +			time_state->info[0].report_id, SENSOR_HUB_SYNC,
> > false);
> >  	/* wait for all values (event) */
> >  	ret = wait_for_completion_killable_timeout(
> >  			&time_state->comp_last_time, HZ*6);
> > diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-
> > sensor-hub.h
> > index 331dc377c275..dc12f5c4b076 100644
> > --- a/include/linux/hid-sensor-hub.h
> > +++ b/include/linux/hid-sensor-hub.h
> > @@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct
> > hid_sensor_hub_device *hsdev,
> >  * @attr_usage_id:	Attribute usage id as per spec
> >  * @report_id:	Report id to look for
> >  * @flag:      Synchronous or asynchronous read
> > +* @is_signed:   If true then fields < 32 bits will be sign-
> > extended
> >  *
> >  * Issues a synchronous or asynchronous read request for an input
> > attribute.
> >  * Returns data upto 32 bits.
> > @@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
> >  int sensor_hub_input_attr_get_raw_value(struct
> > hid_sensor_hub_device *hsdev,
> >   					u32 usage_id,
> >   					u32 attr_usage_id, u32
> > report_id,
> > - 					enum sensor_hub_read_flags flag
> > +					enum sensor_hub_read_flags
> > flag,
> > +					bool is_signed
> >  );
> >  
> >  /**
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-10-31 14:20 [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers Hans de Goede
  2018-10-31 14:21 ` Hans de Goede
  2018-11-03 12:26 ` Jonathan Cameron
@ 2018-11-13 13:09 ` Bastien Nocera
  2018-11-13 13:34   ` Hans de Goede
  2 siblings, 1 reply; 8+ messages in thread
From: Bastien Nocera @ 2018-11-13 13:09 UTC (permalink / raw)
  To: Hans de Goede, Srinivas Pandruvada, Jonathan Cameron, Jiri Kosina,
	Benjamin Tissoires
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio, linux-input

On Wed, 2018-10-31 at 15:20 +0100, Hans de Goede wrote:
> Before this commit sensor_hub_input_attr_get_raw_value() failed to
> take
> the signedness of 16 and 8 bit values into account, returning e.g.
> 65436 instead of -100 for the z-axis reading of an accelerometer.

Anything I need to change in iio-sensor-proxy for this?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-11-13 13:09 ` Bastien Nocera
@ 2018-11-13 13:34   ` Hans de Goede
  0 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2018-11-13 13:34 UTC (permalink / raw)
  To: Bastien Nocera, Srinivas Pandruvada, Jonathan Cameron,
	Jiri Kosina, Benjamin Tissoires
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio, linux-input

Hi,

On 13-11-18 14:09, Bastien Nocera wrote:
> On Wed, 2018-10-31 at 15:20 +0100, Hans de Goede wrote:
>> Before this commit sensor_hub_input_attr_get_raw_value() failed to
>> take
>> the signedness of 16 and 8 bit values into account, returning e.g.
>> 65436 instead of -100 for the z-axis reading of an accelerometer.
> 
> Anything I need to change in iio-sensor-proxy for this?

No, AFAICT all hid sensors offer the buffered API, so iio-sensor-proxy
will prefer that. This is also likely the cause of why this was not
caught earlier.

Regards,

Hans

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-11-03 12:26 ` Jonathan Cameron
  2018-11-03 15:53   ` Srinivas Pandruvada
@ 2018-11-15  8:20   ` Benjamin Tissoires
  2018-11-16 11:43     ` Jonathan Cameron
  1 sibling, 1 reply; 8+ messages in thread
From: Benjamin Tissoires @ 2018-11-15  8:20 UTC (permalink / raw)
  To: jic23
  Cc: Hans de Goede, Srinivas Pandruvada, Jiri Kosina, knaack.h, lars,
	pmeerw, linux-iio, open list:HID CORE LAYER

On Sat, Nov 3, 2018 at 1:26 PM Jonathan Cameron <jic23@kernel.org> wrote:
>
> On Wed, 31 Oct 2018 15:20:05 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
>
> > Before this commit sensor_hub_input_attr_get_raw_value() failed to take
> > the signedness of 16 and 8 bit values into account, returning e.g.
> > 65436 instead of -100 for the z-axis reading of an accelerometer.
> >
> > This commit adds a new is_signed parameter to the function and makes all
> > callers pass the appropriate value for this.
> >
> > While at it, this commit also fixes up some neighboring lines where
> > statements were needlessly split over 2 lines to improve readability.
> >
> > Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> > Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> Yikes.  Not sure how this was missed for so long.
>
> I'll want the hid maintainers ack for this but probably makes sense
> to take it through IIO.

In case you are still waiting for an answer here, it's an ACK from me:
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Feel free to take it through your tree, I'll deal with the conflicts
if there are any changes to hid-sensor-custom.c or hid-sensor-hub.c in
this cycle.

Cheers,
Benjamin

>
> Is this a for all time thing or should we have an explict Fixes
> tag in place?
>
> I do wonder if we have userspace code working around this which
> is going to get confused, but fingers crossed that's not the case.
>
> Definitely stable material I think.
>
> Jonathan
>
> > ---
> > Changes in v2:
> > -Adjust the kernel doc for the new is_signed parameter to
> >  sensor_hub_input_attr_get_raw_value()
> > -Add Srinivas' Acked-by
> > ---
> >  drivers/hid/hid-sensor-custom.c                  |  2 +-
> >  drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++---
> >  drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
> >  drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
> >  drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
> >  drivers/iio/light/hid-sensor-als.c               |  8 +++++---
> >  drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
> >  drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
> >  drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
> >  drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
> >  drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
> >  drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
> >  include/linux/hid-sensor-hub.h                   |  4 +++-
> >  13 files changed, 52 insertions(+), 25 deletions(-)
> >
> > diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
> > index e8a114157f87..bb012bc032e0 100644
> > --- a/drivers/hid/hid-sensor-custom.c
> > +++ b/drivers/hid/hid-sensor-custom.c
> > @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
> >                                               sensor_inst->hsdev,
> >                                               sensor_inst->hsdev->usage,
> >                                               usage, report_id,
> > -                                             SENSOR_HUB_SYNC);
> > +                                             SENSOR_HUB_SYNC, false);
> >       } else if (!strncmp(name, "units", strlen("units")))
> >               value = sensor_inst->fields[field_index].attribute.units;
> >       else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
> > diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> > index 2b63487057c2..4256fdc5cd6d 100644
> > --- a/drivers/hid/hid-sensor-hub.c
> > +++ b/drivers/hid/hid-sensor-hub.c
> > @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
> >  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> >                                       u32 usage_id,
> >                                       u32 attr_usage_id, u32 report_id,
> > -                                     enum sensor_hub_read_flags flag)
> > +                                     enum sensor_hub_read_flags flag,
> > +                                     bool is_signed)
> >  {
> >       struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
> >       unsigned long flags;
> > @@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> >                                               &hsdev->pending.ready, HZ*5);
> >               switch (hsdev->pending.raw_size) {
> >               case 1:
> > -                     ret_val = *(u8 *)hsdev->pending.raw_data;
> > +                     if (is_signed)
> > +                             ret_val = *(s8 *)hsdev->pending.raw_data;
> > +                     else
> > +                             ret_val = *(u8 *)hsdev->pending.raw_data;
> >                       break;
> >               case 2:
> > -                     ret_val = *(u16 *)hsdev->pending.raw_data;
> > +                     if (is_signed)
> > +                             ret_val = *(s16 *)hsdev->pending.raw_data;
> > +                     else
> > +                             ret_val = *(u16 *)hsdev->pending.raw_data;
> >                       break;
> >               case 4:
> >                       ret_val = *(u32 *)hsdev->pending.raw_data;
> > diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> > index 41d97faf5013..38ff374a3ca4 100644
> > --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> > +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> > @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >       struct hid_sensor_hub_device *hsdev =
> >                                       accel_state->common_attributes.hsdev;
> >
> > @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
> >       case IIO_CHAN_INFO_RAW:
> >               hid_sensor_power_state(&accel_state->common_attributes, true);
> >               report_id = accel_state->accel[chan->scan_index].report_id;
> > +             min = accel_state->accel[chan->scan_index].logical_minimum;
> >               address = accel_3d_addresses[chan->scan_index];
> >               if (report_id >= 0)
> >                       *val = sensor_hub_input_attr_get_raw_value(
> >                                       accel_state->common_attributes.hsdev,
> >                                       hsdev->usage, address, report_id,
> > -                                     SENSOR_HUB_SYNC);
> > +                                     SENSOR_HUB_SYNC,
> > +                                     min < 0);
> >               else {
> >                       *val = 0;
> >                       hid_sensor_power_state(&accel_state->common_attributes,
> > diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > index 36941e69f959..88e857c4baf4 100644
> > --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> > @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
> >       case IIO_CHAN_INFO_RAW:
> >               hid_sensor_power_state(&gyro_state->common_attributes, true);
> >               report_id = gyro_state->gyro[chan->scan_index].report_id;
> > +             min = gyro_state->gyro[chan->scan_index].logical_minimum;
> >               address = gyro_3d_addresses[chan->scan_index];
> >               if (report_id >= 0)
> >                       *val = sensor_hub_input_attr_get_raw_value(
> >                                       gyro_state->common_attributes.hsdev,
> >                                       HID_USAGE_SENSOR_GYRO_3D, address,
> >                                       report_id,
> > -                                     SENSOR_HUB_SYNC);
> > +                                     SENSOR_HUB_SYNC,
> > +                                     min < 0);
> >               else {
> >                       *val = 0;
> >                       hid_sensor_power_state(&gyro_state->common_attributes,
> > diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
> > index beab6d6fd6e1..4bc95f31c730 100644
> > --- a/drivers/iio/humidity/hid-sensor-humidity.c
> > +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> > @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
> >                               HID_USAGE_SENSOR_HUMIDITY,
> >                               HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
> >                               humid_st->humidity_attr.report_id,
> > -                             SENSOR_HUB_SYNC);
> > +                             SENSOR_HUB_SYNC,
> > +                             humid_st->humidity_attr.logical_minimum < 0);
> >               hid_sensor_power_state(&humid_st->common_attributes, false);
> >
> >               return IIO_VAL_INT;
> > diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
> > index 406caaee9a3c..94f33250ba5a 100644
> > --- a/drivers/iio/light/hid-sensor-als.c
> > +++ b/drivers/iio/light/hid-sensor-als.c
> > @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> > @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
> >               case  CHANNEL_SCAN_INDEX_INTENSITY:
> >               case  CHANNEL_SCAN_INDEX_ILLUM:
> >                       report_id = als_state->als_illum.report_id;
> > -                     address =
> > -                     HID_USAGE_SENSOR_LIGHT_ILLUM;
> > +                     min = als_state->als_illum.logical_minimum;
> > +                     address = HID_USAGE_SENSOR_LIGHT_ILLUM;
> >                       break;
> >               default:
> >                       report_id = -1;
> > @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
> >                                       als_state->common_attributes.hsdev,
> >                                       HID_USAGE_SENSOR_ALS, address,
> >                                       report_id,
> > -                                     SENSOR_HUB_SYNC);
> > +                                     SENSOR_HUB_SYNC,
> > +                                     min < 0);
> >                       hid_sensor_power_state(&als_state->common_attributes,
> >                                               false);
> >               } else {
> > diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> > index 45107f7537b5..cf5a0c242609 100644
> > --- a/drivers/iio/light/hid-sensor-prox.c
> > +++ b/drivers/iio/light/hid-sensor-prox.c
> > @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> > @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> >               switch (chan->scan_index) {
> >               case  CHANNEL_SCAN_INDEX_PRESENCE:
> >                       report_id = prox_state->prox_attr.report_id;
> > -                     address =
> > -                     HID_USAGE_SENSOR_HUMAN_PRESENCE;
> > +                     min = prox_state->prox_attr.logical_minimum;
> > +                     address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
> >                       break;
> >               default:
> >                       report_id = -1;
> > @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> >                               prox_state->common_attributes.hsdev,
> >                               HID_USAGE_SENSOR_PROX, address,
> >                               report_id,
> > -                             SENSOR_HUB_SYNC);
> > +                             SENSOR_HUB_SYNC,
> > +                             min < 0);
> >                       hid_sensor_power_state(&prox_state->common_attributes,
> >                                               false);
> >               } else {
> > diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > index d55c4885211a..f3c0d41e5a8c 100644
> > --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> >       switch (mask) {
> >       case IIO_CHAN_INFO_RAW:
> >               hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
> > -             report_id =
> > -                     magn_state->magn[chan->address].report_id;
> > +             report_id = magn_state->magn[chan->address].report_id;
> > +             min = magn_state->magn[chan->address].logical_minimum;
> >               address = magn_3d_addresses[chan->address];
> >               if (report_id >= 0)
> >                       *val = sensor_hub_input_attr_get_raw_value(
> >                               magn_state->magn_flux_attributes.hsdev,
> >                               HID_USAGE_SENSOR_COMPASS_3D, address,
> >                               report_id,
> > -                             SENSOR_HUB_SYNC);
> > +                             SENSOR_HUB_SYNC,
> > +                             min < 0);
> >               else {
> >                       *val = 0;
> >                       hid_sensor_power_state(
> > diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > index 1e5451d1ff88..bdc5e4554ee4 100644
> > --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> > +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> >       switch (mask) {
> >       case IIO_CHAN_INFO_RAW:
> >               hid_sensor_power_state(&incl_state->common_attributes, true);
> > -             report_id =
> > -                     incl_state->incl[chan->scan_index].report_id;
> > +             report_id = incl_state->incl[chan->scan_index].report_id;
> > +             min = incl_state->incl[chan->scan_index].logical_minimum;
> >               address = incl_3d_addresses[chan->scan_index];
> >               if (report_id >= 0)
> >                       *val = sensor_hub_input_attr_get_raw_value(
> >                               incl_state->common_attributes.hsdev,
> >                               HID_USAGE_SENSOR_INCLINOMETER_3D, address,
> >                               report_id,
> > -                             SENSOR_HUB_SYNC);
> > +                             SENSOR_HUB_SYNC,
> > +                             min < 0);
> >               else {
> >                       hid_sensor_power_state(&incl_state->common_attributes,
> >                                               false);
> > diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> > index 4c437918f1d2..d7b1c00ceb4d 100644
> > --- a/drivers/iio/pressure/hid-sensor-press.c
> > +++ b/drivers/iio/pressure/hid-sensor-press.c
> > @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
> >       int report_id = -1;
> >       u32 address;
> >       int ret_type;
> > +     s32 min;
> >
> >       *val = 0;
> >       *val2 = 0;
> > @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
> >               switch (chan->scan_index) {
> >               case  CHANNEL_SCAN_INDEX_PRESSURE:
> >                       report_id = press_state->press_attr.report_id;
> > -                     address =
> > -                     HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> > +                     min = press_state->press_attr.logical_minimum;
> > +                     address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> >                       break;
> >               default:
> >                       report_id = -1;
> > @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
> >                               press_state->common_attributes.hsdev,
> >                               HID_USAGE_SENSOR_PRESSURE, address,
> >                               report_id,
> > -                             SENSOR_HUB_SYNC);
> > +                             SENSOR_HUB_SYNC,
> > +                             min < 0);
> >                       hid_sensor_power_state(&press_state->common_attributes,
> >                                               false);
> >               } else {
> > diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> > index beaf6fd3e337..b592fc4f007e 100644
> > --- a/drivers/iio/temperature/hid-sensor-temperature.c
> > +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> > @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
> >                       HID_USAGE_SENSOR_TEMPERATURE,
> >                       HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
> >                       temp_st->temperature_attr.report_id,
> > -                     SENSOR_HUB_SYNC);
> > +                     SENSOR_HUB_SYNC,
> > +                     temp_st->temperature_attr.logical_minimum < 0);
> >               hid_sensor_power_state(
> >                               &temp_st->common_attributes,
> >                               false);
> > diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
> > index 2751dba850c6..3e1abb455472 100644
> > --- a/drivers/rtc/rtc-hid-sensor-time.c
> > +++ b/drivers/rtc/rtc-hid-sensor-time.c
> > @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
> >       /* get a report with all values through requesting one value */
> >       sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
> >                       HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
> > -                     time_state->info[0].report_id, SENSOR_HUB_SYNC);
> > +                     time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
> >       /* wait for all values (event) */
> >       ret = wait_for_completion_killable_timeout(
> >                       &time_state->comp_last_time, HZ*6);
> > diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
> > index 331dc377c275..dc12f5c4b076 100644
> > --- a/include/linux/hid-sensor-hub.h
> > +++ b/include/linux/hid-sensor-hub.h
> > @@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
> >  * @attr_usage_id:    Attribute usage id as per spec
> >  * @report_id:        Report id to look for
> >  * @flag:      Synchronous or asynchronous read
> > +* @is_signed:   If true then fields < 32 bits will be sign-extended
> >  *
> >  * Issues a synchronous or asynchronous read request for an input attribute.
> >  * Returns data upto 32 bits.
> > @@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
> >  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> >                                       u32 usage_id,
> >                                       u32 attr_usage_id, u32 report_id,
> > -                                     enum sensor_hub_read_flags flag
> > +                                     enum sensor_hub_read_flags flag,
> > +                                     bool is_signed
> >  );
> >
> >  /**
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
  2018-11-15  8:20   ` Benjamin Tissoires
@ 2018-11-16 11:43     ` Jonathan Cameron
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2018-11-16 11:43 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Hans de Goede, Srinivas Pandruvada, Jiri Kosina, knaack.h, lars,
	pmeerw, linux-iio, open list:HID CORE LAYER

On Thu, 15 Nov 2018 09:20:23 +0100
Benjamin Tissoires <benjamin.tissoires@redhat.com> wrote:

> On Sat, Nov 3, 2018 at 1:26 PM Jonathan Cameron <jic23@kernel.org> wrote:
> >
> > On Wed, 31 Oct 2018 15:20:05 +0100
> > Hans de Goede <hdegoede@redhat.com> wrote:
> >  
> > > Before this commit sensor_hub_input_attr_get_raw_value() failed to take
> > > the signedness of 16 and 8 bit values into account, returning e.g.
> > > 65436 instead of -100 for the z-axis reading of an accelerometer.
> > >
> > > This commit adds a new is_signed parameter to the function and makes all
> > > callers pass the appropriate value for this.
> > >
> > > While at it, this commit also fixes up some neighboring lines where
> > > statements were needlessly split over 2 lines to improve readability.
> > >
> > > Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> > > Signed-off-by: Hans de Goede <hdegoede@redhat.com>  
> > Yikes.  Not sure how this was missed for so long.
> >
> > I'll want the hid maintainers ack for this but probably makes sense
> > to take it through IIO.  
> 
> In case you are still waiting for an answer here, it's an ACK from me:
> Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> 
> Feel free to take it through your tree, I'll deal with the conflicts
> if there are any changes to hid-sensor-custom.c or hid-sensor-hub.c in
> this cycle.
Cool. Applied to the fixes-togreg branch of iio.git and marked for stable.

Thanks, all,

Jonathan

> 
> Cheers,
> Benjamin
> 
> >
> > Is this a for all time thing or should we have an explict Fixes
> > tag in place?
> >
> > I do wonder if we have userspace code working around this which
> > is going to get confused, but fingers crossed that's not the case.
> >
> > Definitely stable material I think.
> >
> > Jonathan
> >  
> > > ---
> > > Changes in v2:
> > > -Adjust the kernel doc for the new is_signed parameter to
> > >  sensor_hub_input_attr_get_raw_value()
> > > -Add Srinivas' Acked-by
> > > ---
> > >  drivers/hid/hid-sensor-custom.c                  |  2 +-
> > >  drivers/hid/hid-sensor-hub.c                     | 13 ++++++++++---
> > >  drivers/iio/accel/hid-sensor-accel-3d.c          |  5 ++++-
> > >  drivers/iio/gyro/hid-sensor-gyro-3d.c            |  5 ++++-
> > >  drivers/iio/humidity/hid-sensor-humidity.c       |  3 ++-
> > >  drivers/iio/light/hid-sensor-als.c               |  8 +++++---
> > >  drivers/iio/light/hid-sensor-prox.c              |  8 +++++---
> > >  drivers/iio/magnetometer/hid-sensor-magn-3d.c    |  8 +++++---
> > >  drivers/iio/orientation/hid-sensor-incl-3d.c     |  8 +++++---
> > >  drivers/iio/pressure/hid-sensor-press.c          |  8 +++++---
> > >  drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
> > >  drivers/rtc/rtc-hid-sensor-time.c                |  2 +-
> > >  include/linux/hid-sensor-hub.h                   |  4 +++-
> > >  13 files changed, 52 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
> > > index e8a114157f87..bb012bc032e0 100644
> > > --- a/drivers/hid/hid-sensor-custom.c
> > > +++ b/drivers/hid/hid-sensor-custom.c
> > > @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
> > >                                               sensor_inst->hsdev,
> > >                                               sensor_inst->hsdev->usage,
> > >                                               usage, report_id,
> > > -                                             SENSOR_HUB_SYNC);
> > > +                                             SENSOR_HUB_SYNC, false);
> > >       } else if (!strncmp(name, "units", strlen("units")))
> > >               value = sensor_inst->fields[field_index].attribute.units;
> > >       else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
> > > diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> > > index 2b63487057c2..4256fdc5cd6d 100644
> > > --- a/drivers/hid/hid-sensor-hub.c
> > > +++ b/drivers/hid/hid-sensor-hub.c
> > > @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
> > >  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> > >                                       u32 usage_id,
> > >                                       u32 attr_usage_id, u32 report_id,
> > > -                                     enum sensor_hub_read_flags flag)
> > > +                                     enum sensor_hub_read_flags flag,
> > > +                                     bool is_signed)
> > >  {
> > >       struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
> > >       unsigned long flags;
> > > @@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> > >                                               &hsdev->pending.ready, HZ*5);
> > >               switch (hsdev->pending.raw_size) {
> > >               case 1:
> > > -                     ret_val = *(u8 *)hsdev->pending.raw_data;
> > > +                     if (is_signed)
> > > +                             ret_val = *(s8 *)hsdev->pending.raw_data;
> > > +                     else
> > > +                             ret_val = *(u8 *)hsdev->pending.raw_data;
> > >                       break;
> > >               case 2:
> > > -                     ret_val = *(u16 *)hsdev->pending.raw_data;
> > > +                     if (is_signed)
> > > +                             ret_val = *(s16 *)hsdev->pending.raw_data;
> > > +                     else
> > > +                             ret_val = *(u16 *)hsdev->pending.raw_data;
> > >                       break;
> > >               case 4:
> > >                       ret_val = *(u32 *)hsdev->pending.raw_data;
> > > diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> > > index 41d97faf5013..38ff374a3ca4 100644
> > > --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> > > +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> > > @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >       struct hid_sensor_hub_device *hsdev =
> > >                                       accel_state->common_attributes.hsdev;
> > >
> > > @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
> > >       case IIO_CHAN_INFO_RAW:
> > >               hid_sensor_power_state(&accel_state->common_attributes, true);
> > >               report_id = accel_state->accel[chan->scan_index].report_id;
> > > +             min = accel_state->accel[chan->scan_index].logical_minimum;
> > >               address = accel_3d_addresses[chan->scan_index];
> > >               if (report_id >= 0)
> > >                       *val = sensor_hub_input_attr_get_raw_value(
> > >                                       accel_state->common_attributes.hsdev,
> > >                                       hsdev->usage, address, report_id,
> > > -                                     SENSOR_HUB_SYNC);
> > > +                                     SENSOR_HUB_SYNC,
> > > +                                     min < 0);
> > >               else {
> > >                       *val = 0;
> > >                       hid_sensor_power_state(&accel_state->common_attributes,
> > > diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > > index 36941e69f959..88e857c4baf4 100644
> > > --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > > +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> > > @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > > @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
> > >       case IIO_CHAN_INFO_RAW:
> > >               hid_sensor_power_state(&gyro_state->common_attributes, true);
> > >               report_id = gyro_state->gyro[chan->scan_index].report_id;
> > > +             min = gyro_state->gyro[chan->scan_index].logical_minimum;
> > >               address = gyro_3d_addresses[chan->scan_index];
> > >               if (report_id >= 0)
> > >                       *val = sensor_hub_input_attr_get_raw_value(
> > >                                       gyro_state->common_attributes.hsdev,
> > >                                       HID_USAGE_SENSOR_GYRO_3D, address,
> > >                                       report_id,
> > > -                                     SENSOR_HUB_SYNC);
> > > +                                     SENSOR_HUB_SYNC,
> > > +                                     min < 0);
> > >               else {
> > >                       *val = 0;
> > >                       hid_sensor_power_state(&gyro_state->common_attributes,
> > > diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
> > > index beab6d6fd6e1..4bc95f31c730 100644
> > > --- a/drivers/iio/humidity/hid-sensor-humidity.c
> > > +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> > > @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
> > >                               HID_USAGE_SENSOR_HUMIDITY,
> > >                               HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
> > >                               humid_st->humidity_attr.report_id,
> > > -                             SENSOR_HUB_SYNC);
> > > +                             SENSOR_HUB_SYNC,
> > > +                             humid_st->humidity_attr.logical_minimum < 0);
> > >               hid_sensor_power_state(&humid_st->common_attributes, false);
> > >
> > >               return IIO_VAL_INT;
> > > diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
> > > index 406caaee9a3c..94f33250ba5a 100644
> > > --- a/drivers/iio/light/hid-sensor-als.c
> > > +++ b/drivers/iio/light/hid-sensor-als.c
> > > @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > > @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
> > >               case  CHANNEL_SCAN_INDEX_INTENSITY:
> > >               case  CHANNEL_SCAN_INDEX_ILLUM:
> > >                       report_id = als_state->als_illum.report_id;
> > > -                     address =
> > > -                     HID_USAGE_SENSOR_LIGHT_ILLUM;
> > > +                     min = als_state->als_illum.logical_minimum;
> > > +                     address = HID_USAGE_SENSOR_LIGHT_ILLUM;
> > >                       break;
> > >               default:
> > >                       report_id = -1;
> > > @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
> > >                                       als_state->common_attributes.hsdev,
> > >                                       HID_USAGE_SENSOR_ALS, address,
> > >                                       report_id,
> > > -                                     SENSOR_HUB_SYNC);
> > > +                                     SENSOR_HUB_SYNC,
> > > +                                     min < 0);
> > >                       hid_sensor_power_state(&als_state->common_attributes,
> > >                                               false);
> > >               } else {
> > > diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> > > index 45107f7537b5..cf5a0c242609 100644
> > > --- a/drivers/iio/light/hid-sensor-prox.c
> > > +++ b/drivers/iio/light/hid-sensor-prox.c
> > > @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > > @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> > >               switch (chan->scan_index) {
> > >               case  CHANNEL_SCAN_INDEX_PRESENCE:
> > >                       report_id = prox_state->prox_attr.report_id;
> > > -                     address =
> > > -                     HID_USAGE_SENSOR_HUMAN_PRESENCE;
> > > +                     min = prox_state->prox_attr.logical_minimum;
> > > +                     address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
> > >                       break;
> > >               default:
> > >                       report_id = -1;
> > > @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
> > >                               prox_state->common_attributes.hsdev,
> > >                               HID_USAGE_SENSOR_PROX, address,
> > >                               report_id,
> > > -                             SENSOR_HUB_SYNC);
> > > +                             SENSOR_HUB_SYNC,
> > > +                             min < 0);
> > >                       hid_sensor_power_state(&prox_state->common_attributes,
> > >                                               false);
> > >               } else {
> > > diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > > index d55c4885211a..f3c0d41e5a8c 100644
> > > --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > > +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> > > @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > >       switch (mask) {
> > >       case IIO_CHAN_INFO_RAW:
> > >               hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
> > > -             report_id =
> > > -                     magn_state->magn[chan->address].report_id;
> > > +             report_id = magn_state->magn[chan->address].report_id;
> > > +             min = magn_state->magn[chan->address].logical_minimum;
> > >               address = magn_3d_addresses[chan->address];
> > >               if (report_id >= 0)
> > >                       *val = sensor_hub_input_attr_get_raw_value(
> > >                               magn_state->magn_flux_attributes.hsdev,
> > >                               HID_USAGE_SENSOR_COMPASS_3D, address,
> > >                               report_id,
> > > -                             SENSOR_HUB_SYNC);
> > > +                             SENSOR_HUB_SYNC,
> > > +                             min < 0);
> > >               else {
> > >                       *val = 0;
> > >                       hid_sensor_power_state(
> > > diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > > index 1e5451d1ff88..bdc5e4554ee4 100644
> > > --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> > > +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> > > @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > >       switch (mask) {
> > >       case IIO_CHAN_INFO_RAW:
> > >               hid_sensor_power_state(&incl_state->common_attributes, true);
> > > -             report_id =
> > > -                     incl_state->incl[chan->scan_index].report_id;
> > > +             report_id = incl_state->incl[chan->scan_index].report_id;
> > > +             min = incl_state->incl[chan->scan_index].logical_minimum;
> > >               address = incl_3d_addresses[chan->scan_index];
> > >               if (report_id >= 0)
> > >                       *val = sensor_hub_input_attr_get_raw_value(
> > >                               incl_state->common_attributes.hsdev,
> > >                               HID_USAGE_SENSOR_INCLINOMETER_3D, address,
> > >                               report_id,
> > > -                             SENSOR_HUB_SYNC);
> > > +                             SENSOR_HUB_SYNC,
> > > +                             min < 0);
> > >               else {
> > >                       hid_sensor_power_state(&incl_state->common_attributes,
> > >                                               false);
> > > diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> > > index 4c437918f1d2..d7b1c00ceb4d 100644
> > > --- a/drivers/iio/pressure/hid-sensor-press.c
> > > +++ b/drivers/iio/pressure/hid-sensor-press.c
> > > @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
> > >       int report_id = -1;
> > >       u32 address;
> > >       int ret_type;
> > > +     s32 min;
> > >
> > >       *val = 0;
> > >       *val2 = 0;
> > > @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
> > >               switch (chan->scan_index) {
> > >               case  CHANNEL_SCAN_INDEX_PRESSURE:
> > >                       report_id = press_state->press_attr.report_id;
> > > -                     address =
> > > -                     HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> > > +                     min = press_state->press_attr.logical_minimum;
> > > +                     address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
> > >                       break;
> > >               default:
> > >                       report_id = -1;
> > > @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
> > >                               press_state->common_attributes.hsdev,
> > >                               HID_USAGE_SENSOR_PRESSURE, address,
> > >                               report_id,
> > > -                             SENSOR_HUB_SYNC);
> > > +                             SENSOR_HUB_SYNC,
> > > +                             min < 0);
> > >                       hid_sensor_power_state(&press_state->common_attributes,
> > >                                               false);
> > >               } else {
> > > diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> > > index beaf6fd3e337..b592fc4f007e 100644
> > > --- a/drivers/iio/temperature/hid-sensor-temperature.c
> > > +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> > > @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
> > >                       HID_USAGE_SENSOR_TEMPERATURE,
> > >                       HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
> > >                       temp_st->temperature_attr.report_id,
> > > -                     SENSOR_HUB_SYNC);
> > > +                     SENSOR_HUB_SYNC,
> > > +                     temp_st->temperature_attr.logical_minimum < 0);
> > >               hid_sensor_power_state(
> > >                               &temp_st->common_attributes,
> > >                               false);
> > > diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
> > > index 2751dba850c6..3e1abb455472 100644
> > > --- a/drivers/rtc/rtc-hid-sensor-time.c
> > > +++ b/drivers/rtc/rtc-hid-sensor-time.c
> > > @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
> > >       /* get a report with all values through requesting one value */
> > >       sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
> > >                       HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
> > > -                     time_state->info[0].report_id, SENSOR_HUB_SYNC);
> > > +                     time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
> > >       /* wait for all values (event) */
> > >       ret = wait_for_completion_killable_timeout(
> > >                       &time_state->comp_last_time, HZ*6);
> > > diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
> > > index 331dc377c275..dc12f5c4b076 100644
> > > --- a/include/linux/hid-sensor-hub.h
> > > +++ b/include/linux/hid-sensor-hub.h
> > > @@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
> > >  * @attr_usage_id:    Attribute usage id as per spec
> > >  * @report_id:        Report id to look for
> > >  * @flag:      Synchronous or asynchronous read
> > > +* @is_signed:   If true then fields < 32 bits will be sign-extended
> > >  *
> > >  * Issues a synchronous or asynchronous read request for an input attribute.
> > >  * Returns data upto 32 bits.
> > > @@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
> > >  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
> > >                                       u32 usage_id,
> > >                                       u32 attr_usage_id, u32 report_id,
> > > -                                     enum sensor_hub_read_flags flag
> > > +                                     enum sensor_hub_read_flags flag,
> > > +                                     bool is_signed
> > >  );
> > >
> > >  /**  
> >  

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-11-16 21:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-10-31 14:20 [PATCH v2] iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers Hans de Goede
2018-10-31 14:21 ` Hans de Goede
2018-11-03 12:26 ` Jonathan Cameron
2018-11-03 15:53   ` Srinivas Pandruvada
2018-11-15  8:20   ` Benjamin Tissoires
2018-11-16 11:43     ` Jonathan Cameron
2018-11-13 13:09 ` Bastien Nocera
2018-11-13 13:34   ` Hans de Goede

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox