summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2018-10-31 15:20:05 +0100
committerBen Hutchings <ben@decadent.org.uk>2019-02-11 17:54:05 +0000
commitab77f8541e7116a4d5f127f9eda2a4f87709fa0f (patch)
tree03b0e4668f153cb0d7df1762a7a8b84645ff55f0
parent29a806c51fa209de6fbc7f849766eff5c3e301b7 (diff)
iio/hid-sensors: Fix IIO_CHAN_INFO_RAW returning wrong values for signed numbers
commit 0145b50566e7de5637e80ecba96c7f0e6fff1aad upstream. 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. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> [bwh: Backported to 3.16: - sensor_hub_input_attr_get_raw_value() doesn't take a sync/async flag parameter - In sensor_hub_input_attr_get_raw_value() keep using data->pending instead of hsdev->pending - In magn_3d_read_raw() keep using chan->scan_index intstead of chan->address - Drop changes in hid-sensor-{custom,humidity,temperature} - Adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--drivers/hid/hid-sensor-hub.c13
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c5
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c5
-rw-r--r--drivers/iio/light/hid-sensor-als.c8
-rw-r--r--drivers/iio/light/hid-sensor-prox.c8
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c8
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c8
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c8
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c2
-rw-r--r--include/linux/hid-sensor-hub.h4
10 files changed, 47 insertions, 22 deletions
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index e244e449cbba..248a436e222a 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -257,7 +257,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)
+ u32 attr_usage_id, u32 report_id,
+ bool is_signed)
{
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
unsigned long flags;
@@ -282,10 +283,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
switch (data->pending.raw_size) {
case 1:
- ret_val = *(u8 *)data->pending.raw_data;
+ if (is_signed)
+ ret_val = *(s8 *)data->pending.raw_data;
+ else
+ ret_val = *(u8 *)data->pending.raw_data;
break;
case 2:
- ret_val = *(u16 *)data->pending.raw_data;
+ if (is_signed)
+ ret_val = *(s16 *)data->pending.raw_data;
+ else
+ ret_val = *(u16 *)data->pending.raw_data;
break;
case 4:
ret_val = *(u32 *)data->pending.raw_data;
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 54e464e4bb72..1c4b0248d7bf 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -112,6 +112,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -125,12 +126,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
hid_sensor_power_state(&accel_state->common_attributes, true);
msleep_interruptible(poll_value * 2);
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,
HID_USAGE_SENSOR_ACCEL_3D, address,
- report_id);
+ report_id,
+ 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 fa034a3dad78..15fe41bf7c67 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -112,6 +112,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -125,12 +126,14 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
hid_sensor_power_state(&gyro_state->common_attributes, true);
msleep_interruptible(poll_value * 2);
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);
+ report_id,
+ min < 0);
else {
*val = 0;
hid_sensor_power_state(&gyro_state->common_attributes,
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 96e71e103ea7..f032906ab5ff 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -81,6 +81,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -89,8 +90,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
switch (chan->scan_index) {
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;
@@ -109,7 +110,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
*val = sensor_hub_input_attr_get_raw_value(
als_state->common_attributes.hsdev,
HID_USAGE_SENSOR_ALS, address,
- report_id);
+ report_id,
+ 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 c95b9682f0da..607a6fb5adb0 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -74,6 +74,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -82,8 +83,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;
@@ -103,7 +104,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
*val = sensor_hub_input_attr_get_raw_value(
prox_state->common_attributes.hsdev,
HID_USAGE_SENSOR_PROX, address,
- report_id);
+ report_id,
+ 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 b2b0937d5133..0de504b70c93 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -112,6 +112,7 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -125,14 +126,15 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
hid_sensor_power_state(&magn_state->common_attributes, true);
msleep_interruptible(poll_value * 2);
- report_id =
- magn_state->magn[chan->scan_index].report_id;
+ report_id = magn_state->magn[chan->scan_index].report_id;
+ min = magn_state->magn[chan->scan_index].logical_minimum;
address = magn_3d_addresses[chan->scan_index];
if (report_id >= 0)
*val = sensor_hub_input_attr_get_raw_value(
magn_state->common_attributes.hsdev,
HID_USAGE_SENSOR_COMPASS_3D, address,
- report_id);
+ report_id,
+ min < 0);
else {
*val = 0;
hid_sensor_power_state(&magn_state->common_attributes,
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 2478f6c2ef25..e037175d813a 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -112,6 +112,7 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -125,14 +126,15 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
hid_sensor_power_state(&incl_state->common_attributes, true);
msleep_interruptible(poll_value * 2);
- 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);
+ report_id,
+ 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 759b153f1955..7118aa68a866 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -78,6 +78,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
u32 address;
int ret_type;
s32 poll_value;
+ s32 min;
*val = 0;
*val2 = 0;
@@ -86,8 +87,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;
@@ -106,7 +107,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
*val = sensor_hub_input_attr_get_raw_value(
press_state->common_attributes.hsdev,
HID_USAGE_SENSOR_PRESSURE, address,
- report_id);
+ report_id,
+ min < 0);
hid_sensor_power_state(&press_state->common_attributes,
false);
} else {
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 965a9da70867..4f4c336e9a64 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);
+ time_state->info[0].report_id, 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 51f7ccadf923..0d182665f142 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -149,6 +149,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
* @usage_id: Attribute usage id of parent physical device as per spec
* @attr_usage_id: Attribute usage id as per spec
* @report_id: Report id to look for
+* @is_signed: If true then fields < 32 bits will be sign-extended
*
* Issues a synchronous read request for an input attribute. Returns
* data upto 32 bits. Since client can get events, so this call should
@@ -157,7 +158,8 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
- u32 attr_usage_id, u32 report_id);
+ u32 attr_usage_id, u32 report_id,
+ bool is_signed);
/**
* sensor_hub_set_feature() - Feature set request
* @report_id: Report id to look for